This document describes the architectural direction and the implemented architectural foundations of the Cyber Ware repository. It is intended as a readable blueprint for architects and contributors who want to understand how the platform is structured, why the main technical decisions were made, and which capabilities are already present in the codebase.
Status markers use repository evidence. An item is marked
[x]only when logic is implemented in this repository today.
Cyber Ware is a secure, modular XaaS development framework and middleware. It sits between low-level infrastructure and product-specific logic, providing reusable modkit, runtime foundations, and service-level modules that teams compose into services, applications and platforms.
This repository contains the Rust implementation. The Cyber Ware ecosystem may include additional repositories in other languages (e.g. C#, Go) sharing the same architecture patterns, API conventions, and security model.
Cyber Ware is not a ready-to-use service — it is a set of well-integrated libraries (modules) that XaaS vendors compose into their own products. Vendors decide which modules to include, how to combine them into services, and on what infrastructure to run. Every module owns its API surface and database, communicates with other modules via a Rust-native SDK that facades local vs. remote calls, and is fully infrastructure- and deployment-agnostic.
- Cyber Ware doesn't optimize for minimalism or the lowest barrier to entry
Cyber Ware does not aim to be the simplest or smallest framework for building SaaS or AI applications. It intentionally prioritizes explicit structure, security, scalability,governance, composability, and long-term evolvability over quick-start simplicity or minimal configuration.
- Cyber Ware doesn't provide a rich catalog of end-user services out of the box
Cyber Ware does not aim to ship a comprehensive set of ready-made, end-user SaaS services (e.g. CRM, ticketing, billing products) as part of its core. Its primary focus is the foundational layer — runtime, control plane, GenAI capabilities, workflows, and extensibility — on top of which vendors and product teams build their own complete SaaS offerings.
- Cyber Ware doesn't attempt to replace cloud infrastructure or PaaS layers
Cyber Ware is not a replacement for cloud providers or infrastructure platforms such as AWS, Azure, GCP, or on-prem orchestration stacks. It does not offer physical infrastructure, networking, container orchestration, or low-level resource scheduling. Instead, Cyber Ware intentionally positions itself above IaaS/PaaS and below vendor-developed SaaS, focusing on application-level services, governance, and GenAI enablement.
These patterns describe the repository's architectural direction. Most are enforced in the codebase today; forward-looking items explicitly state that status.
Cyber Ware allows building XaaS services using ready-to-use building blocks, domain model elements, and APIs where security is structural, not opt-in. Every API handler enforces authentication, authorization, tenant isolation, and scoped database access by default. The platform owns the security data path — from token validation through policy enforcement to row-level database scoping — so module developers get multi-tenancy and granular access control without implementing it themselves.
The architecture makes the insecure path harder than the secure one. Module developers get tenant-scoped, authorized database access by default.
How. The security data-path is a linear chain:
- Static checks — Custom lints and CI workflows catch violations at build time (e.g. domain layer importing infra, raw SQL outside migrations).
- Authentication — API Gateway validates tokens and injects
SecurityContextinto every request. Modules never parse tokens. - Authorization — Handlers call
PolicyEnforcer, which queries the PDP plugin. The PDP returns a decision plus row-level constraints, compiled into anAccessScope. - Database scoping — Modules access the database through
SecureConn, which appliesAccessScopeas automatic WHERE clauses to implement tenant-level isolation and ABAC. Raw connections are not exposed. - Credentials storage — vendors can use the
credstoremodule to manage secrets. - Outbound traffic — External HTTP goes through
oagw, which centralizes credential injection and egress policy.
Why. There is no "unscoped" shortcut to accidentally use.
Cyber Ware treats custom static analysis as a core architectural mechanism, not a best-effort coding aid. Architectural boundaries, API conventions, GTS usage rules, and security restrictions are enforced during builds through repository-specific Dylint rules.
How. The workspace includes tools/dylint_lints/, a dedicated Dylint suite that checks contract-layer purity, DTO placement and schema derives, domain-layer isolation, direct SQL restrictions, versioned REST paths, mandatory OperationBuilder metadata, OData extension usage, GTS identifier correctness, and other cross-cutting rules. These lints run alongside the normal Rust toolchain and CI checks, which means architectural violations fail fast before review or runtime.
This is a shift-left quality mechanism: the repository pushes correctness, consistency, and architecture conformance into compile-time and CI-time validation rather than relying only on code review.
Why. In a large modular platform, architecture decays quickly if it lives only in markdown. Dylint makes the desired structure executable and keeps both human contributors and AI-assisted changes inside the intended design envelope.
Cyber Ware organizes its codebase into three tiers:
- Modkit (
libs/) — a set of libraries providing the low-level substrate: API middleware, DB access, error definitions, transport abstractions, security primitives, observability, macros, and shared utilities. - System modules (
modules/system/) — Pre-built system modules that form the control plane: inbound/outbound API gateway, authn/authz resolvers, tenant resolver, resource groups, type registry, node registry, usage collection, and related cross-cutting services. - Service modules (
modules/) — Ready-to-use and vendor-developed business modules built on top of the platform: serverless runtime, GenAI subsystems, event system, chat engine, file parser, and domain-specific services.
See: MODULES.md
Cyber Ware follows a DDD-light structure in which domain logic is kept free from transport and infrastructure details, while REST/gRPC adapters and infra layers handle boundary-specific concerns.
How. The standard module layout separates SDK contracts, module bootstrap, domain logic, API adapters, and infrastructure. Domain types and services live under domain/, REST DTOs and route wiring stay in API-facing layers, and persistence/integration logic stays in infra. This boundary is reinforced not only by structure but also by custom Dylints and the #[domain_model] macro requirement for domain-layer types.
Why. Business logic stays easier to test, reuse, and evolve because it is not entangled with HTTP, database, or framework details. At the same time, adapter code remains explicit about where transport translation and persistence concerns begin.
Cyber Ware composes systems by declaration and discovery rather than by hand-written assembly code. Modules declare capabilities and dependencies; the runtime discovers them, builds a dependency-ordered registry, and wires the system from those declarations.
How. ModKit uses the inventory crate to collect module registrators across the workspace and feed them into ModuleRegistry::discover_and_build(). The resulting registry is topologically sorted from declared dependencies before the host runtime starts executing phases. This means a module contributes its capabilities once, in its own crate, and then becomes available to any host binary without bespoke composition glue.
Why. This keeps composition scalable as the repository grows. Adding a module does not require editing a central switchboard, and dependency ordering becomes a platform guarantee rather than an application-specific convention.
Cyber Ware modules do not invent their own startup and shutdown semantics. The platform defines an explicit lifecycle with ordered phases, barrier points, and dependency-aware teardown, and modules integrate into that lifecycle through capabilities.
How. HostRuntime runs a shared sequence of phases including pre_init, DB migration, init, post_init, REST wiring, gRPC wiring, start/stop, and OoP orchestration. System modules run first where required, post_init is a barrier phase that begins only after all init hooks complete, and shutdown runs in reverse dependency order with a platform deadline for graceful stop. Cancellation tokens propagate through the runtime so background work cooperates with shutdown rather than outliving the host.
Why. This gives all modules one predictable operational model. Contributors can rely on stable ordering guarantees, shared cancellation semantics, and consistent startup/shutdown behavior instead of encoding lifecycle assumptions ad hoc in each module.
Persistence follows the same separation-of-concerns model as APIs and security: a module owns its schema and migrations, but the runtime owns privileged execution of those migrations and withholds raw privileged DB access from module code.
How. Modules expose migrations through DatabaseCapability::migrations(). During the DB phase, HostRuntime resolves the underlying database handle from the runtime-managed DbManager, collects migrations from each module, and executes them through the migration runner. Module code typically works with DBProvider, SecureConn, or higher-level repository abstractions rather than direct privileged connections, while migration history is tracked per module.
Why. Schema evolution remains modular and local to the owning module, but privilege stays centralized in the runtime. That reduces the chance of accidental cross-module interference and keeps persistence governance aligned with the repository's secure-by-default posture.
Cyber Ware does not ship ready-to-use services. It ships a set of well-integrated libraries that vendors compose into their own service binaries. Each module is infrastructure-agnostic and deployment-agnostic, supporting three deployment shapes:
- Single-node — all modules in one process. Suitable for edge devices, on-prem appliances, development, and testing.
- Multi-node — modules distributed across processes or machines over REST API or gRPC, without container orchestration. Suitable for bare-metal on-prem or small-scale deployments.
- Kubernetes cluster — modules as containerized services with full orchestration and cloud-native operations.
Modules talk to each other through a Rust-native SDK that facades the communication interface (local vs. remote) and encapsulates internal logic. The platform provides DB-agnostic persistence (SeaORM-based) and infrastructure-agnostic cluster primitives (distributed cache, distributed locks, leader election, service discovery).
Every module's public API lives in a dedicated SDK package (<module>-sdk/) containing only the interface definition, transport-agnostic models, and error types. The implementation depends on the SDK, never the other way around.
How. The compiler enforces this boundary — implementation-private types are not in scope for consumers. REST endpoints use OperationBuilder, which requires each route to declare its method, path, auth posture, request/response schemas, and error types at registration time. OpenApiRegistry collects these declarations and generates /openapi.json automatically. Because metadata lives next to handler wiring (not in a separate spec file), it stays in sync with the code by construction.
Why. Refactoring module internals is safe as long as the SDK interface stays compatible. Consumers can develop and test against SDK types alone. The OpenAPI spec is always consistent with the running code.
Cyber Ware separates service logic from service packaging. Module logic lives in libraries; final service binaries compose those libraries for a specific deployment shape.
How. Module contracts are transport-agnostic: in-process modules register local adapters in ClientHub; out-of-process modules register REST/gRPC clients implementing the same SDK interface. A YAML config field (runtime.type: local | oop) switches modes without code changes. The platform provides DB-agnostic persistence through a SeaORM-based SecureConn abstraction and infrastructure-agnostic cluster primitives (distributed cache, distributed locks, leader election, service discovery) that resolve against operator-selected backends at startup.
Why. This makes Cyber Ware not just cloud-provider-agnostic, but deployment-topology-agnostic. Teams develop and test locally in single-node mode, deploy bare-metal services for on-prem or edge products, and scale to Kubernetes when needed — all from the same module code and contracts.
Cyber Ware does not treat HTTP shape, query conventions, and API description as local stylistic choices. Modules follow one API style built around versioned paths, typed route registration, shared middleware, OpenAPI generation, and standard query patterns such as OData for filtering and ordering.
How. OperationBuilder is the authoritative route-registration mechanism in ModKit. A route declares method, versioned path, auth posture, license posture, request schema, response schema, tags, summary, and registered error responses in one place. OpenApiRegistry collects these declarations into the generated /openapi.json. For query shape, ModKit exposes OData helpers such as with_odata_filter, with_odata_orderby, and with_odata_select, and workspace Dylints enforce that REST endpoints use the standardized extension methods rather than ad-hoc query conventions.
This produces one recognizable API dialect across modules:
- Versioned endpoints such as
/resource-group/v1/groups - Uniform OpenAPI publication through the gateway
- Shared pagination/filter/order conventions
- OData-style filtering for collection resources where applicable
- Consistent auth, rate-limit, timeout, and observability behavior at the gateway
- Rate limiting — governor-based rate limiter with policy headers and inflight semaphores is implemented in the API Gateway middleware stack (
modules/system/api-gateway/src/middleware/rate_limit.rs). OAGW has a separate rate-limiting implementation for outbound traffic. - [~] License posture declaration — OperationBuilder declaration and base-license gate implemented; per-feature entitlement validation against license resolver pending.
Why. Consumers, SDK authors, tests, docs, and gateway behavior all stay predictable. A module does not invent its own filtering language, pagination rules, or error envelope, so cross-module tooling and client generation remain feasible.
Cyber Ware is converging on one platform-wide error vocabulary instead of each module inventing its own transport-level failure categories. The canonical error model aligns with the 16 standard gRPC categories and maps them into REST via RFC-9457 Problem documents while preserving machine-readable type identity through GTS.
Status. Foundation implemented; repository-wide migration still in progress.
How. libs/modkit-canonical-errors/ defines CanonicalError with the following 16 categories: Cancelled, Unknown, InvalidArgument, DeadlineExceeded, NotFound, AlreadyExists, PermissionDenied, ResourceExhausted, FailedPrecondition, Aborted, OutOfRange, Unimplemented, Internal, ServiceUnavailable, DataLoss, and Unauthenticated. Each category has typed context, an HTTP mapping, and a stable GTS type identifier. The canonical error stack then renders these errors as RFC-9457 Problem responses for HTTP while keeping the underlying category model suitable for future gRPC and internal SDK alignment.
This gives the platform one error taxonomy across:
- REST wire responses
- module and SDK boundaries
- future gRPC transport
- observability and retry classification
- schema registration and contract validation
Why. Standardized error categories reduce drift, make retry behavior machine-readable, and keep API, SDK, and transport layers aligned. The same architectural decision also enables generated documentation and stronger static enforcement of allowed error patterns.
See more: docs/arch/errors/DESIGN.md
The next major architectural addition is a unified cluster coordination capability for distributed Cyber Ware deployments. The intent is to make cross-instance coordination a first-class platform concern rather than something each module reinvents with ad-hoc locks, local registries, or deployment-specific glue.
How. The cluster module is intended to provide four platform-level primitives behind stable contracts: distributed cache, leader election, distributed locks, and service discovery. Consumer modules will declare what they need and the platform will resolve those primitives against operator-selected backends. The design direction already visible in repository docs is that backends may vary by primitive, capability requirements will be validated at startup, cache-backed defaults will exist for other primitives, and watch/lifecycle semantics will be standardized across the coordination surface.
Why. Existing modules already show the need for shared coordination patterns such as node discovery, leader-elected background work, distributed rate limiting, and backend-dependent service location. Elevating these into one platform primitive keeps module contracts stable across deployment shapes and prevents each module from inventing incompatible coordination behavior.
Cyber Ware modules and their API handlers have deep integration with the typical XaaS platform backbone: multi-tenancy, licensing and quota management, usage collection, event systems, credential management, and so on. Cyber Ware provides its own backbone modules for these concerns, but they are designed as replaceable — vendors can integrate with their existing backbone via the plugin system (e.g. connect an existing product catalog, provisioning system, or license enforcement engine) so the entire Cyber Ware module fleet works with the vendor's own platform infrastructure.
Authorization, authentication, tenancy, ingress, outbound traffic, type registries, and runtime orchestration are each implemented as a regular module with its own SDK, lifecycle, and API surface — not hidden inside the framework.
How. Each concern publishes a public interface in an SDK package. The implementation registers itself in ClientHub (the typed service locator). Consumers resolve the interface at runtime and never depend on the implementation package. Example: authz-resolver-sdk defines the authorization interface; consumer modules resolve it from ClientHub without importing the resolver's internals. The same pattern applies to authn-resolver, tenant-resolver, types-registry, oagw, etc.
Why. Concerns can be swapped, tested in isolation, or deployed out-of-process without touching callers. The runtime assembles only the modules a given deployment needs.
The majority of Cyber Ware modules define an extensible domain model. Object metadata, types, and behavior can be customized through the Global Type System (GTS) — define new event types, user settings, LLM model attributes, permission schemas, and more without modifying existing modules or endpoints. CRUD API handlers can be further customized via API hooks and callbacks implemented as serverless functions and workflows, enabling vendors to inject domain-specific logic at well-defined extension points.
New implementations are added without changing existing modules.
How. A host module defines a plugin interface in its SDK and registers the plugin schema in the type registry. Plugin modules implement the interface and register as scoped clients in ClientHub, keyed by GTS instance ID. The host discovers plugins at runtime and routes to the selected one via a vendor config field. Adding a new backend (e.g. a custom auth provider) means writing a new plugin — the host and all its consumers stay unchanged.
Why. Third-party integrations are isolated with no dependency on platform internals beyond the SDK. Host module tests remain stable when plugins are added or removed.
New data types are added without modifying existing modules or endpoints.
How. The Global Type System provides versioned, schema-validated type definitions. New data types (event formats, document schemas, serverless workflows and functions, permissions, license types, custom attributes) can appear in the system without modifying existing endpoints or storage. In Rust, Cyber Ware derives GTS definitions directly from source code types and then registers the resulting JSON Schemas in the Types Registry. That means event schemas, plugin contracts, and other typed contracts can be generated from Rust code in the same way OpenAPI is generated from route declarations, instead of being maintained as hand-written side artifacts.
Why. Incompatible schema changes are caught at registration time. The type surface grows without code changes to existing modules, and contracts stay machine-verifiable.
See more in: docs/REPO_PLAYBOOK.md
Rust is a strong fit for Cyber Ware core modules because this repository is building a platform layer for long-lived XaaS systems, where concurrency, correctness, and maintainability matter more than short-term implementation speed alone.
-
Compile-time safety
- Rust eliminates broad classes of memory and concurrency failures before runtime.
-
Refactoring confidence
- Strong typing and compiler diagnostics make large architectural changes safer, especially when contracts span multiple crates.
-
Good fit for reusable platform code
- Libraries such as ModKit, security layers, transport layers, and registries benefit from predictable performance and explicit interfaces.
-
Static analysis as part of architecture
- Rust's ecosystem, combined with Clippy and custom Dylints, allows many project rules to become enforceable at build time.
-
Operational efficiency
- A low-footprint runtime makes it practical to run realistic local/edge systems, end-to-end tests, and service combinations without depending on heavyweight environments.
The monorepo model is a natural fit because Cyber Ware is a co-evolving platform rather than a loose collection of unrelated packages.
-
Atomic contract evolution
- Core contracts and all consumers can be updated together.
-
Shared quality gates
- Lints, CI checks, testing flows, and security scanning stay consistent across the entire platform.
-
Integrated architecture validation
- Requirements, design, code, tests and examples can be validated in one workspace.
-
Better support for generated and assisted development
- A single repository context improves the feedback loop for architectural changes that cut across many crates.
The repository maps directly to the three-tier module hierarchy described in §3.2:
-
libs/— Modkit- Libraries providing the low-level substrate: API middleware, DB access, error definitions, transport abstractions, security primitives, observability, macros, and shared utilities.
- This layer defines the engineering rules and runtime substrate that higher tiers reuse.
-
modules/system/— System modules- Control-plane and cross-cutting system modules: API ingress, module orchestration, authn/authz, tenancy, resource groups, types registry, nodes registry, outbound API gateway, and related services.
- These modules carry much of the architectural weight of the repository because they establish the runtime model and platform guarantees.
-
modules/— Service modules- Outside
modules/system/, the broadermodules/tree contains business and domain modules that deliver product functionality: serverless runtime, GenAI subsystems, event system, chat engine, file parser, and more (see MODULES.md for the full inventory and roadmap). - All service modules follow the same ModKit patterns, SDK conventions, and security model established by the modkit and system module tiers.
- Outside
Additional assembly lives in apps/, where executable applications compose modules into examples of runnable systems.
ModKit is the central framework of this repository. It turns the module architecture into a reusable runtime discipline.
The cyberware-modkit crate and adjacent libraries provide the common substrate on which the rest of the repository is built.
What ModKit provides:
-
Inventory-based module discovery
- Modules are discovered via the
inventorycrate and assembled into a registry.
- Modules are discovered via the
-
Modules lifecycle orchestration
HostRuntimeexecutes explicit phases such aspre_init, DB migrations,init,post_init, REST wiring, gRPC wiring, start/stop, and OoP orchestration.
-
Type-safe in-process communication
ClientHubregisters and resolves typed module clients without leaking transport details.
-
REST and OpenAPI composition
OperationBuilderandOpenApiRegistrymake route metadata part of the architecture rather than an afterthought.
-
Module-owned database migrations executed by the runtime
- Modules provide migrations; the runtime executes them without handing out raw privileged DB access to modules.
-
Security primitives
SecurityContext,AccessScope, secure ORM patterns, and policy-enforcement integration are part of the stack.
-
Observability primitives
- Tracing, OpenTelemetry integration, request IDs, and health endpoints are implemented in foundation and system layers.
-
Transport flexibility
- In-process, REST, and gRPC all fit the same modular model.
-
SSE streaming infrastructure
- ModKit provides
SseBroadcaster<T>for typed server-sent event fan-out over tokio broadcast channels, andOperationBuilder::sse_json<T>()for first-class SSE route registration with automatic OpenAPI schema generation. Modules use this for real-time streaming (e.g. AI token delivery) without implementing low-level event-stream plumbing.
- ModKit provides
-
Transactional outbox
modkit-dbincludes a multi-stage transactional outbox pipeline (enqueue → sequence → process) with two processing strategies: transactional (exactly-once, in-DB) and leased (at-least-once, idempotent). The outbox supports partition-based parallelism, dead-letter lifecycle, and multi-database backends (PostgreSQL, MySQL, SQLite). Modules enqueue domain events inside the caller's transaction and the outbox pipeline delivers them asynchronously with reliable ordering.
-
Typed module configuration
ModuleCtxprovidesconfig::<T>()andconfig_expanded::<T>()for typed, per-module configuration loaded from YAML sections. Modules that can operate with defaults usemodule_config_or_default; modules that require configuration usemodule_config_required. The#[derive(ExpandVars)]macro expands${VAR}placeholders from environment variables in marked fields, keeping secrets out of config files.
See more: docs/modkit_unified_system/README.md
Cyber Ware defines how every authenticated request flows through a fixed platform-owned sequence before reaching module business logic. This pattern is typical for XaaS control plane services: the platform resolves cross-cutting concerns such as authentication, authorization, and license validation up front, and provides explicit placeholders where that processing can be customized through plugins or extensions defined with GTS, for example to add a new licenseable feature or a new user role.
sequenceDiagram
participant C as Client
participant GW as API Gateway
participant AuthN as AuthN Resolver
participant Lic as License Resolver
participant Mod as Execution Module
participant AuthZ as AuthZ Resolver
participant DB as Database (SecureConn)
C->>GW: HTTP Request
GW->>AuthN: Validate token → SecurityContext
AuthN-->>GW: SecurityContext
GW->>Lic: Validate license feature for route
Lic-->>GW: Allowed / Denied
GW->>Mod: Handler(SecurityContext)
Mod->>AuthZ: PolicyEnforcer → AccessScope
AuthZ-->>Mod: AccessScope + row-level constraints
Mod->>DB: Entity::find().secure().scope_with(&scope)
DB-->>Mod: Scoped query results
Mod-->>GW: Response
GW-->>C: HTTP Response
The API Gateway owns authentication (token →
SecurityContext) and license validation. Module domain services own authorization: they callPolicyEnforcer, which queries the AuthZ Resolver and compiles the result into anAccessScope. The module then passes that scope toSecureConnfor row-level database filtering. Module code never performs token parsing or tenant resolution directly. License validation is currently implemented at the base-license level; per-feature entitlement is pending. Usage collection (modules/system/usage-collector/) is planned but not yet implemented.
See MODULES.md for the full module inventory.
In Cyber Ware, a module is a logical runtime component with explicit dependencies, capabilities, API surface, and lifecycle.
- Modules are registered and discovered through ModKit.
- Modules can expose typed SDK APIs.
- Modules can expose REST endpoints.
- Modules can own database schema and migrations.
- Modules can participate in background runtime lifecycle.
- Modules can run in-process or out-of-process.
The standard module layout follows a Domain-Driven Design (DDD-light) structure:
-
SDK crate for stable contracts
-
module crate for bootstrap and capability declaration
-
domain layer for core logic
-
API adapters for REST/gRPC boundaries
-
infra layer for persistence and integration
-
SDK pattern is documented and used.
-
REST DTOs and transport concerns are separated from domain logic.
-
Domain-layer rules are reinforced by architectural lints.
Cyber Ware supports both in-process and out-of-process module execution. The logical module model and contracts remain the same regardless of the physical deployment boundary.
The default mode is in-process composition: modules share one runtime, communicate through typed clients, and are wired together by ModKit.
-
ClientHubimplements typed in-process client resolution. - Module lifecycle and REST/gRPC assembly are handled by the shared runtime.
Modules can also run as separate processes communicating via gRPC.
-
HostRuntimecontains explicit OoP orchestration hooks. -
modkit-transport-grpcexists as a transport library. -
docs/modkit_unified_system/09_oop_grpc_sdk_pattern.mddocuments the pattern. -
examples/oop-modules/demonstrates the model with calculator examples.
Security in Cyber Ware spans the language choice, module boundaries, DB access rules, policy enforcement, and CI controls. See docs/security/SECURITY.md for the full security architecture.
-
Rust safety baseline
- Memory safety, strong typing, and strict lint posture are part of the default development model.
-
Secure ORM / compile-time scoping
- Secure DB access and scoping rules are enforced through ModKit DB patterns and macros.
-
Split AuthN/AuthZ architecture
- Authentication resolution and authorization resolution are modeled as separate system services.
-
SecurityContextpropagation model- Request identity and scope flow through the platform as explicit data rather than thread-local magic.
-
Policy-based tenant and group scoping
- Tenant hierarchy and resource groups act as platform inputs to authorization decisions.
-
Outbound API security boundary
- OAGW (Outbound API Gateway) centralizes outbound HTTP policy, credential resolution, and egress hardening.
-
Credential handling architecture
credstore(modules/credstore/) and secrecy-aware types are present for secret handling.
-
Static and CI security gates
- Clippy, custom Dylints,
cargo-deny, CodeQL, fuzzing, and related scanners are part of the repo.
- Clippy, custom Dylints,
Cyber Ware's authorization model is built on explicit tenant-owned data boundaries. The tenant topology is a hierarchical single-root tree: every resource belongs to exactly one tenant, tenant isolation is the default posture, and parent-to-child visibility can be constrained by barriers such as self_managed. Authorization distinguishes the subject's home tenant from the context tenant used for an operation, and resource groups add an optional grouping layer for access control within tenant boundaries rather than replacing tenant ownership.
- Tenant topology is documented as a single-root hierarchy with parent/child relationships.
- Tenant ownership is a first-class authorization dimension, typically carried as
owner_tenant_id. - Barrier semantics exist for restricting parent visibility into subtrees.
- Resource groups are tenant-scoped and act as an additional access-control structure, not a replacement for tenant isolation.
See more in: arch/authorization/TENANT_MODEL.md and arch/authorization/RESOURCE_GROUP_MODEL.md
Cyber Ware uses a PEP → PDP → AccessScope pipeline for authorization. Domain services act as the PEP: they receive SecurityContext, build an AccessRequest, and call PolicyEnforcer, which delegates to the AuthZ resolver client. The PDP returns a decision plus constraints, and those constraints are compiled into an AccessScope that the secure DB layer applies as scoped query conditions. In practice, this means module business logic does not embed policy engines or hard-code role semantics; it consumes platform authorization results expressed as tenant, resource, owner, and type filters.
-
modules/system/authz-resolver/provides a PDP client abstraction viaauthz-resolver-sdk. -
PolicyEnforcerwrapsAuthZResolverClient; domain services callpolicy_enforcer.access_scope_with(ctx, resource_type, action, resource_id, properties). -
AccessScopecarries four constraint dimensions: tenant, resource, owner, and type. -
ScopableEntityrequires each DB entity to declare which column maps to each scope dimension. -
pep_propertiesdefinesOWNER_TENANT_IDandRESOURCE_ID, and these properties are used in current modules. -
authz-resolverplugs in viaClientHub; the platform does not hard-code a specific PDP. -
A default
authz-resolverimplementation with a built-in role model. -
Custom role definition by tenant admins.
-
Documentation for attaching existing policy managers to Cyber Ware.
-
Documentation of which resource types and actions each system module exposes.
-
A platform-level role catalog with roles available out of the box.
Example PEP call pattern from modules/simple-user-settings/simple-user-settings/src/domain/service.rs:
let scope = self
.policy_enforcer
.access_scope_with(
ctx,
&SETTINGS_RESOURCE,
actions::GET,
Some(user_id),
&AccessRequest::new().resource_property(pep_properties::OWNER_TENANT_ID, tenant_id),
)
.await?;The
authz-resolver-sdkcrate defines the enforcement interface used by PEPs, includingAuthZResolverClient,PolicyEnforcer, request/response models, and constraint compilation helpers. The PDP implementation is pluggable: Cyber Ware resolves it throughClientHuband plugin registration rather than bundling a single mandatory authorization engine in core.
See more details in: arch/authorization/DESIGN.md
- API Gateway builds a unified HTTP surface with health endpoints, middleware, auth, request IDs, tracing, timeouts, and docs endpoints.
- Rate limiting — governor-based rate limiter with policy headers and inflight semaphores is implemented in the API Gateway middleware stack. OAGW has a separate rate-limiting implementation for outbound traffic.
- [~] License posture declaration — OperationBuilder declaration and base-license gate implemented; per-feature entitlement validation against license resolver pending.
-
OpenApiRegistryandOperationBuilderare implemented in ModKit. -
/openapi.jsonand/docsare served by the API gateway. - OData extensions are implemented in
OperationBuilderfor standardized$filter,$select, and$orderbysupport. - Workspace Dylints enforce versioned endpoints and standardized OData extension usage.
The important architectural point is that OpenAPI is generated from the same Rust route declarations that wire the running service. Cyber Ware does not maintain a separate hand-authored HTTP contract description.
- GTS schemas can be generated directly from Rust types
- Plugin specifications already use this pattern in SDK crates such as
authn-resolver-sdkandmini-chat-sdk. - Generated GTS JSON Schemas are intended for registration in the Types Registry.
- GTS-specific Dylints validate identifier correctness and prevent unsupported schema-generation patterns such as
schema_for!on GTS structs.
This is the non-HTTP counterpart to OpenAPI generation. OpenAPI describes REST endpoints; GTS-generated JSON Schema describes platform contracts and typed data beyond REST, including plugin specs, events, and other globally identified contracts. Together they let Cyber Ware derive both API and non-API contracts from Rust source rather than duplicating schemas manually.
- RFC-9457
Problemhandling is implemented in the ModKit/API stack. -
libs/modkit-canonical-errors/provides typed canonical categories. -
libs/modkit-canonical-errors-macro/provides resource-scoped error helpers. - The canonical error foundation covers the 16 gRPC-aligned categories used as the platform-wide failure vocabulary.
- Repository-wide migration to canonical errors is not complete yet.
The canonical error model stabilizes failure semantics, improves machine-readability, reduces ad-hoc error drift, and aligns REST, future gRPC, and internal domain errors. It also connects failure semantics to GTS-backed type identity, so error categories become part of the platform contract surface rather than just human-readable messages.
- OpenTelemetry tracing initialization exists in
libs/modkit/src/telemetry/. - API Gateway implements request IDs, tracing, timeout layers, body limits, and structured access logging.
- API Gateway exposes
/healthand/healthz. - Rate limiting — governor-based rate limiter is implemented in the API Gateway middleware stack. OAGW has a separate rate-limiting implementation for outbound traffic.
- The repo contains CI workflows and test infrastructure aligned with operational quality.
Cyber Ware defines a dual-layer testing strategy with an explicit zero-overlap rule between tiers. Unit and integration tests run in-process against SQLite :memory: with mocked AuthZ, covering domain invariants, validation, error chains, DTO conversions, and seeding logic — no HTTP, no real database. End-to-end tests (pytest against a running cyberware-server with real Database) verify only integration seams that unit tests cannot see: JSON wire format, real AuthZ wiring, DB-specific SQL, and cross-module SDK boundaries. Each unit test must pass three gating questions: (1) does it verify deterministic domain logic, (2) is it atomic and fast, and (3) does removing it reduce confidence in domain correctness.
See more: docs/modkit_unified_system/12_unit_testing.md and docs/modkit_unified_system/13_e2e_testing.md
