The stance reads coherently once one distinction is on the table. At every layer where an open specification exists, Actionary implements a thin adapter. At every layer where the “ecosystem” is an opinionated framework masquerading as a standard, Actionary owns the code.
The stance follows Cockburn’s Hexagonal Architecture (2005), Wiggins’s Twelve-Factor App (2011), and Martin’s Chapter 32 “Frameworks Are Details” from Clean Architecture (2017), applied consistently. The adapters are open because the point of an adapter is portability. The core is owned because business logic encodes decisions specific to the domain.
What’s open at the boundary
Seven substrates, each a public specification with multiple compatible implementations:
- PostgreSQL 16.
pg_dumpproduces a portable backup of the whole stack, including thepgvectorretrieval index. - S3-API.
shared/storage/storage_adapter.pyswaps between AWS S3, Cloudflare R2, MinIO, and Backblaze B2 with one env var. Presigned uploads are the industry-standard shape. - Redis wire protocol. Any protocol-compatible store — Dragonfly, KeyDB, Valkey, ElastiCache, Upstash — is a swap target.
- OpenTelemetry. Traces, metrics, and logs emit through vendor-neutral OTLP. The application tier stays free of vendor-specific observability SDKs.
- Model Context Protocol. The agent surface is exposed through Anthropic’s open specification. Claude Desktop, Cursor, Zed, Sourcegraph Cody, and Continue.dev all speak it.
- OAuth 2.1 with DCR and PKCE. IETF-standard trust flows for SSO and machine identity. Any DCR-compliant client can register; any OIDC IdP can be the identity source.
- HTTP with OpenAPI. The public REST surface is described at
/.well-known/openapi.json. SDK generation is@hey-api/openapi-tsrunning against the schema — zero hand-written API types.
Every LLM provider is an adapter too. Anthropic, OpenAI, Bedrock, Azure OpenAI, and Gemini ship as full streaming implementations behind one LLMProvider Protocol. Per-tenant primary + fallback with automatic failover on provider_unavailable.
What’s owned at the core
Five layers of code Actionary maintains directly, without an imported orchestration framework:
- The RAG pipeline —
services/core_api/application/upload_indexer_service.py(extract, chunk, embed, persist) andservices/core_api/infra/repositories/content_asset_chunks_repository.py(hand-written SQL againstpgvector). - The workflow engine —
workflow_runswithFOR UPDATE SKIP LOCKEDstep claims. Durable execution on Postgres, one fewer stateful service in the deploy topology. - Agent orchestration — propose-then-execute on the MCP tool surface, destructive-confirm staging in the agent loop. The loop is code Actionary owns end to end.
- The entity metadata layer —
entity_configreads throughentity_service.py. One schema drives the SPA, the admin API, and the MCP tool surface. - Permission enforcement — Postgres RLS keyed on
app.current_tenant_idunder aNOSUPERUSER NOBYPASSRLSrequest role, plus a_permissionscontract on every list response.
The roads not taken, named with reasoning
- LangChain, LlamaIndex. Orchestration middleware. Adopting them means adopting their
Chain/Runnable/Retrieverabstractions and their breaking-change history. The chunker + embedder + retriever code that already exists is a few hundred lines and does exactly what the domain needs. - Pinecone, Weaviate. Hosted vector stores. Adopting them means data leaves Postgres — backup surface splits in two, audit surface splits in two, the
record_accessvisibility gate stops applying to the external store. - Temporal, Airflow. Durable-execution frameworks. Adopting them means a second stateful service in the deploy topology when
workflow_runson Postgres already delivers the same idempotent-step guarantee. - Kafka, RabbitMQ. Dedicated brokers. Redis lists via
BLPOPwith an orphan sweep against a Postgres state table is enough at Actionary’s shape. A dedicated broker is the right choice when throughput or cross-region delivery guarantees demand it; that threshold is ahead of us.
Every one of these is a valid architecture for a codebase built around them. The stance is about which layer of the stack imports the framework.
Fifteen principles, 1974 to 2024
The architecture is assembled from foundational principles. The full catalogue traces every layer to a principle the industry has agreed on for two decades or more.
- Separation of Concerns — Dijkstra, 1974. Three-layer backend enforced by CI.
- Least Privilege — Saltzer & Schroeder, 1975. Five-role DB model; RLS at the substrate.
- PoEAA — Repository, Service Layer, Domain Model — Fowler, 2002. 87 repository files. Zero inline SQL in routers.
- Domain-Driven Design — Evans, 2003. The metadata-driven entity model is DDD applied to a runtime substrate.
- Hexagonal Architecture — Cockburn, 2005. Two HTTP adapters (REST + MCP) over one application core.
- Twelve-Factor App — Wiggins, 2011. Twelve out of twelve.
- Clean Architecture — Martin, 2012 / 2017. Dependencies point inward; a CI lint rejects the reverse.
- Trunk-Based Development — Forsgren, Humble, Kim, 2018. Eight-phase health-gated deploy, expand/contract migration policy.
- Contract-First API — OpenAPI Initiative, 2011 / 2017. Typed SDK regenerated on every schema change.
- OpenTelemetry — CNCF, 2019. Distributed tracing across browser, core-api, MCP server, LLM providers.
- Row-Level Security — Postgres 9.5 (2016), popularised by Supabase. Migration 338 enabled it on every tenant-scoped table.
- Zero Trust — NIST SP 800-207 / Google BeyondCorp. Every request re-derives
session_kind; every MCP tool call re-checks per-row visibility. - Feature-Sliced Design — community, ongoing. 21 feature modules under
apps/web/src/features/. - Metadata-driven substrate — the industry pattern. Adding a field is a database row.
- Model Context Protocol — Anthropic, 2024. 72 MCP tools, one canonical catalogue.
The takeaway
Every foundational principle is 15 to 50 years old. Every modern principle is production-proven at cloud-scale organisations today — Netflix, Uber, AWS, Microsoft, Apple, Google, Stripe, Supabase. The architecture is a coherent stack of those principles. The substrate it produces is portable at every wire boundary and coherent at every application layer. That is what enterprise-grade means.