
Architecture Foundation
- 4 installs
- 253 repo stars
- Updated August 4, 2026
- majiayu000/claude-arsenal
Turns an architecture discussion into explicit boundaries, contracts, validation gates, and a small execution plan before coding.
About
Helps design or audit architecture by identifying a project's shape, choosing minimal boundaries, and explaining existing structure before proposing changes. A developer uses it to produce a spec, prevent stacked one-off PRs, or audit migration debt.
- Search-first: inspect existing docs, entrypoints, APIs, issues before proposing
- Classifies work as boundary creation, completion, or deletion
Architecture Foundation by the numbers
- 4 all-time installs (skills.sh)
- Ranked #1,241 of 1,879 Documentation skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/majiayu000/claude-arsenal --skill architecture-foundationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 4 |
|---|---|
| repo stars | ★ 253 |
| Last updated | August 4, 2026 |
| Repository | majiayu000/claude-arsenal ↗ |
What it does
Turns an architecture discussion into explicit boundaries, contracts, validation gates, and a small execution plan before coding.
Files
Architecture Foundation
Overview
Use this skill to turn an architecture discussion into explicit boundaries, contracts, validation gates, and a small execution plan. The goal is not to copy an admired project, but to identify the project's shape and choose the minimum architecture that keeps ownership, effects, errors, and tests clear. For large existing repos, first explain the architecture they already have, then decide whether the work is boundary creation, boundary completion, or boundary deletion.
When To Use
- The user asks "what architecture should this use?", "is this stacked work?",
"make a complete spec", "design the runtime", or "compare good libraries".
- The change touches runtime, state ownership, adapters, plugins, event loops,
rendering, schedulers, persistence, or cross-module contracts.
- A repo has many issues/PRs that look individually valid but may not converge
on one architecture.
- A mature repo has duplicated paths, compatibility shims, generated configs,
workflow definitions, or docs that may disagree about the source of truth.
- A new skill, framework, library, or large feature needs a foundation guide
before implementation.
Do not use this for small, local fixes where the existing architecture is obvious and no boundary decision is needed.
Workflow
1. Search first.
- Inspect existing architecture docs, entrypoints, manifests, module trees,
public APIs, open issues/PRs, and tests before proposing new structure.
- If the user names a reference project, verify current source or official docs
before treating it as evidence.
- For existing repos, also inspect generated/config artifacts, migration files,
background workers, cron jobs, adapters, and the largest files/tests.
2. Classify the project shape.
- Simple library: stable API plus internal implementation.
- CLI or developer tool: command layer, core operations, IO adapters, reporter.
- API gateway or model router: transport, auth/accounting, routing policy,
provider adapters, billing/settlement, observability.
- Long-running runtime: state root, scheduler, drivers, observability, shutdown.
- Lifecycle/composition framework: dependency graph, construction phase,
runtime hooks, rollback, shutdown, and test harness.
- Event/cache/reconcile controller: watch/list input, cache/projection,
queue/backpressure, worker/reconciler, retry, and drain.
- Config/module platform: canonical config, adapters, module lifecycle,
reload order, rollback, cleanup, and plugin host interfaces.
- UI or app shell: state ownership, event protocol, renderer/platform boundary,
headless tests.
- Service framework: domain core, application services, transport, storage,
middleware, error-to-response boundary.
- Agent or workflow system: task model, scheduler, provider adapters, event log,
replay/test harness.
3. Choose one primary state ownership model.
- App-owned entities and handles for native UI/editor runtimes.
- State plus typed message for enumerated UI/application workflows.
- Virtual DOM/signals when renderer portability and declarative UI dominate.
- Typed state or service-instance state for services and middleware.
- Event log plus projection/outbox for workflows, billing, async jobs, and
reconciliation systems.
- World/resource/system model only when data-parallel ECS is a product fit.
- Snapshot database or input facts for incremental analysis tools.
- Streaming pipeline for one-shot CLI tools and batch processors.
4. Draw the foundation boundaries.
product/app: entrypoints, user workflows, product-specific orchestration.core/domain: pure models, invariants, decisions, typed errors, no IO.runtime/application: lifecycle, scheduling, event dispatch, state mutation.adapters/backends: OS, renderer, provider, filesystem, network, database.plugins/components: optional capabilities behind explicit contracts.testing/headless: deterministic drivers, fake adapters, contract tests.
5. Audit existing boundary health before adding tasks.
- Name the current source of truth for each contract: code, database table,
SQL seed, JSON/YAML config, generated docs, or external provider contract.
- Mark duplicated paths as
intentional bridge,legacy compatibility, or
accidental fork; require an exit condition for compatibility paths.
- Prefer a convergence/deletion plan over a new abstraction when the existing
architecture is directionally correct but half migrated.
- Treat generated files and docs as consumers unless the repo explicitly makes
them authoritative.
6. Write the contracts before tasks.
- Ownership: who owns state, handles, resources, caches, and mutation rights.
- Lifecycle: init, ready, run/tick/frame/request, shutdown, cleanup.
- Effect contract: which layer may persist, call providers, bill, publish
messages, mutate projections, or only emit effects for another layer.
- Event/action: how external events become typed commands/messages/actions.
- Effects: which layer may touch IO, processes, network, OS handles, GPU, DOM,
databases, or providers.
- Error policy: what is recoverable, user-visible, fatal, diagnostic-only, or
converted at a boundary.
- Config/resources: build-time, startup-time, runtime; owner and invalidation.
- Observability: logs, metrics, traces, queue depth, frame/runtime telemetry.
- Tests: unit, contract, headless, fake adapter, integration, platform/E2E.
7. Produce a spec, not just a diagram.
- Use
references/spec-template.mdwhen the user needs a durable artifact. - Include non-goals and "do not copy" notes from reference projects.
- For every reference project, separate
borrowfromdo_not_copy; borrow
boundary contracts, not scale artifacts, global registries, generated machinery, historical migrations, or domain-specific complexity.
- Convert the spec into P0/P1/P2 work where each task maps to one contract.
- If issues/PRs already exist, map them to the contracts and identify gaps.
Decision Rules
- Prefer a thin adapter around a mature runtime when the product does not need
to own that runtime.
- Split crates/modules only for stable API boundaries, side-effect isolation,
compile-time isolation, independent tests, or real reuse.
- In existing repos, do not split crates/packages first when the real problem is
duplicated source-of-truth, an unfinished migration, or missing closed-loop tests.
- Keep core free of platform handles, event loops, renderer handles, webviews,
database clients, HTTP requests, process spawning, and environment reads.
- Make hidden global state illegal unless it is deliberately modeled as typed
runtime state or a scoped resource.
- Do not let plugins become architecture escape hatches. Each plugin needs API,
config/permissions when relevant, lifecycle, errors, and tests.
- Do not accept silent degradation. Missing capability must be an explicit
unsupported error, diagnostic, or blank result according to the contract.
Output Shape
For quick answers, return:
verdict:
chosen_shape:
state_owner:
boundaries:
contracts:
migration_debt:
validation:
risks:
next_steps:For durable planning, create or update an architecture spec with:
objective
current evidence
reference models considered
chosen architecture
boundary map
source-of-truth map
contract matrix
compatibility/deletion plan
issue/PR map
validation matrix
P0/P1/P2 roadmap
open questionsRed Flags
- A proposed module cannot say which boundary it belongs to.
- The design names a trait/config/cache/plugin but does not wire it into
startup, lifecycle, or tests.
- Two state ownership models are mixed without an explicit bridge.
- Two files, configs, SQL seeds, or docs claim to be the source of truth for the
same product contract.
- A compatibility shim or legacy path has no owner, test, telemetry, or removal
condition.
- Platform callbacks directly mutate core state.
- Errors become warnings plus fallback for user-visible behavior.
- Tests only cover the final UI/CLI and cannot drive the runtime headlessly.
- The plan says "match X project" but cannot state what not to copy.
References
- Read
references/rust-architecture-patterns.mdwhen designing Rust crates,
runtimes, UI frameworks, app shells, schedulers, services, or developer tools.
- Read
references/go-architecture-patterns.mdwhen designing Go modules,
packages, services, ports/adapters, context-aware APIs, or concurrency flows.
- Read
references/spec-template.mdwhen producing a repo-facing spec. - Use
agents/openai.yamlonly when a separate architecture review agent is
needed for cross-checking the chosen boundaries or migration plan.
interface:
display_name: "Architecture Foundation"
short_description: "Design architecture boundaries before coding"
default_prompt: "Use $architecture-foundation to design the core runtime and adapter boundaries before implementation."
Go Architecture Patterns
Use this reference when the target project is Go or Go-heavy. Go architecture is usually less about frameworks and more about package boundaries, small interfaces, explicit effects, context propagation, and tests that exercise the public API.
First Principles
1. Start simple. A small Go module does not need cmd, internal, pkg, clean architecture layers, or a repository interface. 2. Package names are API design. Client code reads package.Name, so names should be short, concrete, and not repetitive. 3. Prefer domain or capability packages over mechanical layers. A package should explain what it does, not just where it sits. 4. Interfaces usually belong to the consumer, not the producer. Accept small interfaces where needed and return concrete types. 5. Keep context.Context request-scoped: pass it as an argument, normally first, and do not store it on long-lived structs. 6. Goroutines need owners. Every spawned goroutine needs a cancellation, shutdown, error, or channel-close story. 7. Errors are values. Return typed or distinguishable errors only when callers can act on them; wrap at boundaries where extra context matters. 8. Use tests to protect package contracts. Prefer public API tests and fake adapters over large mock hierarchies.
Pattern Selection
| Project shape | Useful model | Boundary lesson |
|---|---|---|
| Tiny command or package | One module, one package, maybe one main.go | Do not scaffold before there is real complexity. |
| Multiple commands | cmd/<name> plus supporting packages | Command packages parse config/flags and call core logic. |
| Private app internals | internal/<capability> | Hide packages that are not supported public API. |
| Reusable library | Root package plus small subpackages | Design from client import and pkg.Name usage. |
| HTTP/RPC service | handlers, application use cases, adapters | HTTP types stop at transport boundary; domain stays transport-free. |
| API gateway or model router | transport, auth/accounting, routing policy, provider adapters | Provider quirks stay behind adapters; public request contracts stay stable. |
| Async workflow or billing service | command/outbox, worker, state table, projection, reconciler | Source of truth, idempotency, and reconciliation are explicit contracts. |
| Domain-heavy app | bounded contexts or feature packages | Organize by domain language, not generic models/services/utils. |
| Infrastructure adapters | DB, queue, email, external clients | Concrete adapter structs implement consumer-owned interfaces. |
| Concurrent workflow | context, errgroup, channels, worker pool | Ownership, cancellation, close, and backpressure are contracts. |
Mature Go Reference Models
Use mature projects as pattern evidence, not directory templates. Always write both borrow and do_not_copy.
Small API Library: chi
Borrow:
- Keep the public API close to standard-library types when the standard
contract is already good enough. chi centers on net/http handlers, middleware, and route composition.
- Keep internal state private and expose traversal/inspection APIs only when
they are part of the supported contract.
- Enforce configuration-order invariants at the boundary.
Do not copy:
panic-based configuration errors into operator-facing runtimes.- Global mutable registries for broad plugin or provider capability systems.
- Router shape for background workers, billing, or workflow engines.
Lifecycle Framework: fx
Borrow:
- Separate declaration from effects: constructors build dependencies; lifecycle
hooks own goroutines, listeners, background loops, and shutdown.
- Make startup and shutdown ordered, timeout-bound, rollback-aware, and testable.
- Provide a test harness that can explicitly start and stop the runtime.
Do not copy:
- Reflection DI as a default architecture for normal Go services.
- Unordered value groups for ordered handler/plugin chains.
- Deprecated no-op compatibility APIs without a deletion plan.
Event Cache Reconcile: client-go
Borrow:
- Use watch/list input, cache/projection, queue/backpressure, and reconciler
workers as distinct boundaries.
- Keep event handlers cheap; they enqueue keys and do not run business work.
- Define cache consistency, notification order, retry, drain, and shutdown
semantics.
Do not copy:
- Kubernetes-scale generated informer/lister machinery unless the domain has a
comparable typed API surface.
- Controller complexity when there is no watch stream, projection cache, or
reconcile need.
API SDK Exporter: opentelemetry-go
Borrow:
- Separate public API contracts from SDK/runtime implementation and exporters.
- Put external protocol translation, retry, timeout, queue/drop/block behavior,
and shutdown in exporters or processors.
- Keep host-application safety and API stability explicit.
Do not copy:
- Global delegating providers or global error handlers into business cores;
those are observability ecosystem compatibility mechanisms.
- Provider implementation fields in public request schemas.
Deterministic State Machine: etcd/raft
Borrow:
- Keep core transition logic pure when ordering, replay, idempotency, or
convergence is the problem.
- Emit effect batches such as
Readyand let the runtime shell own durable
writes, network sends, apply, ticks, cancellation, and recovery.
- Specify effect order, especially durable-before-send rules.
Do not copy:
- Consensus-specific complexity such as terms, quorum, async storage writes, or
panic-level invariants unless the product is actually a consensus system.
- State-machine shells for ordinary CRUD or simple request/response services.
Config Module Platform: Caddy
Borrow:
- Name the canonical runtime config. Treat human config formats as adapters
that produce canonical config.
- Give modules explicit IDs, host interfaces, provisioning, validation,
cleanup, and context-owned lifecycle.
- For reloadable systems, provision new state before replacing old state, then
clean up the old context.
Do not copy:
- Init-time global module registration, reflect-heavy loading, or Admin API
hot config mutation into ordinary services by default.
- A module platform unless real extension or many same-lifecycle capabilities
justify it.
Operational Service Managers: Prometheus
Borrow:
- Use one composition root to validate config and wire subsystem managers.
- Give each manager explicit dependencies,
Run,Stop,ApplyConfigwhen
needed, metrics, and shutdown order.
- Make reload order explicit and keep config source-of-truth read-only to
consumers.
- Distinguish primary storage from secondary or best-effort sinks.
Do not copy:
- A giant entrypoint unless it is truly only the composition root.
- Server/agent dual-mode complexity, broad feature flags, or migration
interfaces unless the product has that scale and history.
Module And Package Layout
Borrow:
- Use the official module-layout guidance first: basic package, basic command,
supporting packages, multiple commands, and server projects scale differently.
- Use
cmd/<binary>when a repo has multiple commands or a command plus
reusable packages.
- Use
internal/when a package must not become importable public API. - Use
pkg/only when the package is intentionally reusable by external code. - Let package names and exported identifiers read naturally from the caller's
point of view.
Do not copy:
- A "standard project layout" repo as if it were official or mandatory.
- Empty
models,types,utils,common,interfaces, orapipackages. - Layer folders that force every feature through handler/service/repository
even when the feature is small.
Sources:
- https://go.dev/doc/modules/layout
- https://go.dev/blog/package-names
- https://go.dev/wiki/CodeReviewComments
- https://github.com/golang-standards/project-layout
Interfaces And API Boundaries
Borrow:
- Define the interface at the package that consumes the dependency.
- Keep interfaces small and named by behavior:
Reader,Clock,Store,
Publisher, Authorizer, TxRunner.
- Return concrete types from constructors unless callers need an abstraction.
- Accept concrete types when no substitution point is needed.
- Put fakes in tests or test packages when a real adapter is too expensive.
Do not copy:
- Producer-owned interfaces such as
UserRepositoryInterfacenext to the
concrete implementation just to make tests easy.
- Interfaces with many methods that mirror a whole concrete type.
- Generic "service" interfaces without a caller-owned reason.
Sources:
- https://go.dev/wiki/CodeReviewComments
- https://go.dev/blog/package-names
Domain-First And Clean Architecture, Go-Style
Borrow:
- Use Clean Architecture, Hexagonal Architecture, or DDD as dependency
direction rules, not as mandatory folder names.
- Keep domain language in the domain package. If a term has different meaning
in different contexts, split the bounded context.
- Use in-memory adapters early when they help validate domain behavior before
choosing a database.
- Keep transport DTOs and persistence records out of rich domain entities when
tags or external formats would weaken invariants.
Do not copy:
- Java-style layer hierarchies, abstract factories, and interface stacks.
- A repository per table when the use case needs transaction or aggregate
behavior.
- DDD tactical patterns in CRUD-only systems where simple structs and SQL are
clearer.
Sources:
- https://threedots.tech/go-with-the-domain/
- https://academy.threedots.tech/knowledge/domain-first-approach
- https://academy.threedots.tech/knowledge/bounded-context
- https://academy.threedots.tech/knowledge/dto
- https://www.packtpub.com/en-us/product/domain-driven-design-with-golang-9781804619261
HTTP, Service, Repository, And Transactions
Borrow:
- Handlers translate transport input to application commands and responses.
- Application/use-case code owns transaction boundaries when multiple adapter
operations must commit or roll back together.
- Repositories should express domain operations or aggregate persistence, not
just table CRUD by default.
- External clients and stores are concrete adapters behind consumer-owned
interfaces only when tests or alternate implementations require it.
- Map domain/application errors to HTTP/RPC responses at the transport layer.
Do not copy:
- HTTP request, response, JSON, SQL row, or ORM model types into domain logic.
- A service layer that only forwards calls and adds no policy.
- Transaction APIs that leak through every domain function just because the DB
adapter needs them.
Sources:
- https://go.dev/blog/error-handling-and-go
- https://go.dev/wiki/Errors
- https://threedots.tech/go-with-the-domain/
API Gateways, Model Routers, And Provider Adapters
Borrow:
- Keep the public API contract separate from provider-specific request shapes.
- Route selection, account selection, pricing, and capability policy belong in
application packages, not inside transport handlers or provider clients.
- Provider adapters should own authentication, request/response translation,
retry semantics, provider error classification, and provider telemetry.
- Generated docs, model schemas, workflow configs, and SQL seeds need an
explicit source-of-truth order.
Do not copy:
- Letting downstream provider fields leak into the public request schema.
- Making every provider adapter a special case in controller code.
- Treating generated examples or docs as authoritative when SQL/config/code is
what production actually loads.
- Adding a generic adapter framework before at least two real providers share
the same contract.
Context, Cancellation, And Concurrency
Borrow:
- Pass
context.Contextinto operations that may block, perform IO, or spawn
request-scoped work.
- Use context for deadlines, cancellation, and request-scoped values; not for
optional parameters or long-lived dependencies.
- Pipeline stages need rules for input close, output close, fan-out, fan-in,
cancellation, and error propagation.
- Worker pools and background loops need explicit owner, lifecycle, shutdown,
and observability.
Do not copy:
- Storing request context in service structs.
- Starting goroutines without a cancellation or join path.
- Unbounded channel queues without backpressure and shutdown semantics.
- Pipelines for simple sequential code.
Sources:
- https://go.dev/blog/context-and-structs
- https://go.dev/blog/context
- https://go.dev/blog/pipelines
- https://go.dev/blog/advanced-go-concurrency-patterns
Workflow, Billing, And Reconciliation
Borrow:
- Model async work as explicit state transitions with idempotency keys, owner,
deadline/TTL, retry policy, and terminal states.
- Use an outbox or durable command table when billing, provider calls, or MQ
publishing must survive process crashes.
- Keep projection status separate from the execution log, but define which one
is authoritative for each user/operator question.
- Reconciliation loops need bounded scans, lock ownership, metrics, and tests
for stuck/running/partial-failure states.
Do not copy:
- A worker that silently fixes state without recording why the state changed.
- Billing or settlement logic hidden in controllers because the HTTP path was
the first implementation.
- Multiple cron/worker paths that update the same state without one transition
API or transaction owner.
- Retrying provider calls without an idempotency and billing policy.
Errors, Diagnostics, And Observability
Borrow:
- Return
errorvalues and handle them at the boundary that knows what to do. - Wrap errors when the current layer adds useful operation context.
- Use sentinel or typed errors only when callers need programmatic handling.
- Keep user response messages, logs, metrics, and traces separate from the
low-level error value.
- Panic only for impossible programmer errors or narrow internal unwind paths
that recover to an error at a documented boundary.
Do not copy:
- Parsing error strings to make decisions.
- Logging and returning the same error at every layer.
- Returning bare dependency errors across public package boundaries when they
become accidental API commitments.
- Recovering panics silently.
Sources:
- https://go.dev/wiki/Errors
- https://go.dev/blog/error-handling-and-go
- https://go.dev/blog/defer-panic-and-recover
- https://go.dev/pkg/errors/
Testing And Verification
Borrow:
- Test package contracts through the public API when possible.
- Use table tests for behavior matrixes and golden tests for stable output.
- Use fake adapters for DB, queue, clock, email, and external services when the
contract matters more than the implementation.
- Use integration tests for real DB/network behavior at adapter boundaries.
- Add goroutine-leak, cancellation, race, and shutdown tests for concurrent
services.
Do not copy:
- Deep mock stacks that encode implementation details.
- Tests that require every layer to expose interfaces only for mocking.
- Concurrency tests that assert deterministic ordering unless ordering is part
of the contract.
Sources:
- https://go.dev/wiki/CodeReviewComments
- https://go.dev/doc/modules/layout
Book And Long-Form References
Use books as pattern sources, not rules to copy directly.
Go-specific:
Learning Goby Jon Bodner: idiomatic Go, project design, generics, tooling,
and when to avoid non-Go patterns.
100 Go Mistakes and How to Avoid Themby Teiva Harsanyi: practical failure
modes around concurrency, errors, testing, memory, and performance.
Domain-Driven Design with Golangby Matthew Boyle: applying DDD concepts
to Go business systems.
Go With The Domainby Three Dots Labs: pragmatic domain-first Go examples.
General architecture books that can inform Go but should be adapted:
Domain-Driven Designby Eric Evans.Implementing Domain-Driven Designby Vaughn Vernon.Clean Architectureby Robert C. Martin.Patterns of Enterprise Application Architectureby Martin Fowler.Release It!by Michael Nygard.
Sources:
- https://www.ingramacademic.com/9781098139292/learning-go/
- https://www.pearson.com/en-gb/subject-catalog/p/100-go-mistakes/P200000007212/9781617299599
- https://www.packtpub.com/en-us/product/domain-driven-design-with-golang-9781804619261
- https://threedots.tech/go-with-the-domain/
Go Design Rules For Architecture Specs
1. State the package import graph before drawing layers. 2. Name packages by domain or capability, not generic technical categories. 3. Put interfaces at the consumer boundary and keep them tiny. 4. Return concrete types until an abstraction is needed. 5. Keep HTTP/RPC/DB/queue types out of the domain unless the app is purely infrastructural. 6. Put context, cancellation, timeout, and shutdown in every blocking or goroutine-spawning contract. 7. Make transaction ownership explicit at the use-case/application boundary. 8. Errors should say who can act on them: caller, transport mapper, operator, or developer. 9. For existing services, name the source of truth for public contracts, workflow state, billing state, generated docs, and SQL/config seeds. 10. Mark compatibility paths as bridge, legacy, or accidental fork; require a deletion or convergence condition before adding another path. 11. Avoid new packages until there is a stable concept, separate owner, side-effect boundary, or test boundary. 12. Prefer boring, readable Go over framework-shaped architecture.
Rust Architecture Patterns
Use this reference when the target project is Rust or Rust-heavy. The point is to borrow boundary principles from mature projects, not to copy their folder names or internal complexity.
Pattern Selection
| Project shape | Useful references | Primary state model | Boundary lesson |
|---|---|---|---|
| Native UI/editor runtime | WarpUI, GPUI/Zed | App-owned entities and handles | Keep app state, element lifecycle, platform, and renderer separate. |
| Declarative UI app | Iced | State plus typed message | Make update/view/subscription explicit and testable. |
| Multi-target UI | Dioxus | Virtual DOM plus signals/hooks | Renderer consumes mutation protocol, not business state. |
| App shell/webview desktop | Tauri, Wry, Slint | Core plus runtime plus adapters/plugins | Keep OS/webview/windowing outside core; govern capabilities. |
| Runtime/scheduler | Tokio, Bevy | Runtime drivers or world/resources | Model lifecycle, scheduling, blocking, and resources explicitly. |
| Middleware/service framework | Tower, Axum | Service instance or typed router state | Encode readiness, backpressure, and error-to-response contracts. |
| Developer tool/CLI | rust-analyzer, ripgrep, clap, Cargo | Snapshot DB, input facts, or streaming pipeline | Separate CLI/IO from reusable core and diagnostics. |
| Trait API and diagnostics | serde, tracing, thiserror, anyhow, miette | Protocol traits plus derive or reporting facade | Keep data protocols, observability producers, typed errors, and user-facing reports separate. |
| Protocol/network/security | hyper, reqwest, rustls, quinn, h3 | Protocol state machine plus runtime adapter or client facade | Keep deterministic protocol core, transport, security config, and product API apart. |
| Concurrency primitives | futures-rs, rayon, crossbeam, parking_lot | Async protocol, CPU pool, channels, or locks | Make scheduling ownership, cancellation, backpressure, fairness, and unsafe boundaries explicit. |
| Data/query/storage | Polars, Arrow-rs, SQLx, Diesel, SeaORM | Data model plus query model plus backend adapter | Separate data containers, plans/queries, drivers, schemas, and runtime errors. |
UI And App Runtime Lessons
WarpUI / GPUI style
Borrow:
- App/runtime owns long-lived entities or models.
- Views render ephemeral element trees.
- A presenter/runtime owns build, layout, event dispatch, scene construction,
rendering, invalidation, focus, actions, text, accessibility, and telemetry.
- Platform and renderer are backends with explicit callbacks and resource
lifetimes.
- Headless app contexts test lifecycle without a real OS window.
Do not copy:
- Custom GPU/native UI stacks unless the product needs editor-grade rendering,
input, and performance.
- Central app ownership into a small CRUD app where state plus message is enough.
Sources:
- https://github.com/warpdotdev/warp/tree/master/crates/warpui_core
- https://github.com/warpdotdev/warp/tree/master/crates/warpui
- https://github.com/zed-industries/zed/blob/main/crates/gpui/README.md
- https://zed.dev/blog/gpui-ownership
Iced style
Borrow:
- One application state, typed messages,
update,view, and subscriptions. - Runtime, widget core, renderer, and window shell remain separate.
- Tests can drive update/view or a headless simulator.
Do not copy:
- Giant message enums and one huge update function for domains that need
independent long-lived entities.
Sources:
- https://github.com/iced-rs/iced
- https://docs.iced.rs/iced/trait.Program.html
- https://docs.iced.rs/iced/struct.Subscription.html
Dioxus style
Borrow:
- Keep component model and renderer connected through a mutation protocol.
- Use SSR/headless/native-dom paths as validation surfaces.
- Make signal/read tracking visible enough to reason about invalidation.
Do not copy:
- Web/HTML assumptions into native-only or terminal-only products.
- Hydration/fullstack complexity unless product requirements need it.
Sources:
- https://dioxuslabs.com/learn/0.7/beyond/project_structure/
- https://dioxuslabs.com/learn/0.7/guides/depth/custom_renderer/
- https://github.com/DioxusLabs/dioxus/blob/main/packages/core/src/virtual_dom.rs
App Shell And Platform Lessons
Tauri / Wry / Winit
Borrow:
- Separate application core from runtime glue and concrete platform backend.
- Treat OS windows, webviews, trays, notifications, IPC, and permissions as
runtime or plugin capabilities, not core business logic.
- Make config stage explicit: compile-time, startup-time, or runtime.
Do not copy:
- Macro/codegen/capability machinery for small shells unless the security and
plugin model justify it.
- Direct event loop/window handles in business logic.
Sources:
- https://v2.tauri.app/concept/architecture/
- https://docs.rs/tauri-runtime-wry/latest/tauri_runtime_wry/
- https://docs.rs/winit/latest/winit/application/trait.ApplicationHandler.html
- https://github.com/tauri-apps/wry
Slint style
Borrow:
- Compiler/runtime/backend/renderer separation.
Platform,WindowAdapter, andRenderertraits as platform/rendering
seams.
- Screenshot and interpreter drivers as first-class tests.
Do not copy:
- A DSL or compiler pipeline unless product requirements need design-time
language tooling, embedded support, or multi-language bindings.
Sources:
- https://docs.slint.dev/latest/docs/slint/
- https://github.com/slint-ui/slint/tree/master/internal
- https://snapshots.slint.dev/master/docs/slint/guide/backends-and-renderers/backend_winit/
Runtime, Scheduler, And Service Lessons
Bevy style
Borrow:
- World/resource/system model when data-parallel ECS is a natural fit.
- Explicit schedules, startup/update stages, plugins, diagnostics, and single
tick tests.
Do not copy:
- ECS service-locator patterns into ordinary apps.
- Frame-based scheduling into request/response systems without a real frame
model.
Sources:
- https://bevy.org/learn/quick-start/getting-started/ecs/
- https://docs.rs/bevy/latest/bevy/ecs/resource/trait.Resource.html
- https://docs.rs/bevy/latest/bevy/app/prelude/trait.Plugin.html
Tokio style
Borrow:
- Runtime owns scheduler, IO driver, timer driver, and blocking pool.
- Fairness and blocking rules are part of the architecture contract.
- Metrics and paused-time tests make runtime behavior observable.
Do not copy:
- Nested runtimes or long CPU work on async workers.
- An arbitrary replaceable scheduler trait when builder configuration is enough.
Sources:
- https://docs.rs/tokio/latest/tokio/runtime/index.html
- https://docs.rs/tokio/latest/tokio/runtime/struct.Builder.html
- https://tokio.rs/tokio/topics/testing
Tower / Axum style
Borrow:
- Tiny
Serviceboundary with readiness, call, response, error, and future. - Layers wrap capabilities without protocol-specific core coupling.
- HTTP errors must become responses at the boundary.
Do not copy:
poll_readycomplexity unless backpressure is an actual requirement.- HTTP response types inside pure domain logic.
Sources:
- https://docs.rs/tower/latest/tower/trait.Service.html
- https://docs.rs/axum/latest/axum/error_handling/index.html
- https://docs.rs/axum/latest/axum/extract/struct.State.html
Developer Tool And CLI Lessons
rust-analyzer style
Borrow:
- Syntax, semantic model, IDE facade, VFS, project model, and LSP binary are
distinct layers.
- Input facts and immutable snapshots make long-running incremental analysis
testable.
- Public facade crates should use client terminology, not internal compiler
implementation types.
Do not copy:
- Salsa/VFS/cancellation machinery into one-shot CLIs.
- Internal crates as if they were public API boundaries.
Sources:
- https://rust-analyzer.github.io/book/contributing/architecture.html
- https://rust-lang.github.io/rust-analyzer/hir/index.html
- https://rust-lang.github.io/rust-analyzer/project_model/index.html
ripgrep style
Borrow:
- CLI glue is thin; reusable work sits in matcher, searcher, printer, ignore,
and facade crates.
- Streaming pipeline beats global state for one-shot file processing.
- Library errors stay typed; binary decides display and exit behavior.
Do not copy:
- Many crates before there is clear reuse, API stability, or side-effect
isolation.
- Push/internal iteration if the target library needs a pull-based API.
Sources:
- https://github.com/BurntSushi/ripgrep
- https://github.com/BurntSushi/ripgrep/tree/master/crates
- https://github.com/BurntSushi/ripgrep/blob/master/crates/grep/README.md
clap / Cargo style
Borrow:
- CLI schema, parse, error formatting, and business operation should be
separate.
- Commands should parse flags, load config, call
opsor core, then report. - Integration tests should exercise the real binary when CLI behavior matters.
Do not copy:
- Heavy derive/codegen or historical global context without a product reason.
- Cargo's internal library shape as a stable public API template.
Sources:
- https://docs.rs/clap/latest/clap/trait.Parser.html
- https://docs.rs/clap/latest/clap/error/index.html
- https://doc.rust-lang.org/nightly/nightly-rustc/cargo/index.html
Trait API, Derive, Diagnostics, And Observability
serde style
Borrow:
- Put a small trait protocol between user data structures and external formats.
- Keep derive as an adoption layer; handwritten implementations must remain
possible for precise control.
- Test protocol behavior through format-independent tokens or fake adapters.
Do not copy:
- Visitor/lifetime/attribute complexity for small internal DTO or config types.
- Format-specific behavior in the core trait layer.
Sources:
- https://docs.rs/serde/latest/
- https://docs.rs/serde/latest/src/serde/core/ser/mod.rs.html
- https://serde.rs/impl-deserialize.html
- https://docs.rs/serde_test/latest/serde_test/
tracing style
Borrow:
- Libraries emit spans/events; applications install subscribers/layers.
- Keep instrumentation producers separate from formatting, filtering, storage,
and export backends.
- Use scoped or fake subscribers in tests.
Do not copy:
- Global subscriber installation from a library.
- Dynamic filtering, callsite caching, and layer stacks unless cross-crate
observability is a real product need.
Sources:
- https://github.com/tokio-rs/tracing
- https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html
- https://docs.rs/tracing-subscriber/latest/tracing_subscriber/layer/trait.Layer.html
- https://docs.rs/tracing-attributes/latest/tracing_attributes/attr.instrument.html
thiserror / anyhow / miette style
Borrow:
- Library boundaries expose typed errors or diagnostic-capable types.
- Application boundaries may aggregate with
anyhow::Erroror render reports
with miette::Report.
- Derive is useful for
Display,source,From, and diagnostic metadata,
but the error taxonomy is still an architecture decision.
Do not copy:
anyhow::Erroras the default public library API.- A giant catch-all error enum with
#[from]on every dependency error. - Fancy terminal diagnostics in background services or library internals.
Sources:
- https://docs.rs/thiserror/latest/thiserror/
- https://docs.rs/anyhow/latest/anyhow/
- https://docs.rs/miette/latest/miette/
- https://docs.rs/miette/latest/miette/trait.Diagnostic.html
Configuration protocol style
Borrow:
- Separate source format, partial config layer, merge, final config,
validation, and schema generation.
- Treat configuration diagnostics as first-class user-facing errors.
Do not copy:
- A full config framework for one small static config file.
Sources:
- https://docs.rs/schematic/latest/schematic/
Protocol, Network, And Security Lessons
hyper style
Borrow:
- Low-level protocol libraries should hide HTTP parser/state-machine internals
behind connection, body, client/server, service, runtime, and upgrade APIs.
- Feature flags may select protocol sides and versions when dependencies are
large or optional.
Do not copy:
- HTTP internal state machines into business logic.
- A low-level library facade when the product needs a high-level client.
Sources:
- https://docs.rs/hyper/latest/hyper/
- https://docs.rs/hyper/latest/hyper/client/conn/http1/
- https://docs.rs/hyper/latest/hyper/server/conn/http1/
- https://docs.rs/hyper/latest/hyper/rt/
reqwest style
Borrow:
- A product-grade client facade can hide transport, TLS, redirect, cookie,
proxy, compression, and platform-specific adapters behind ClientBuilder, RequestBuilder, and Response.
- Request construction should be distinct from transport execution.
- Error values should preserve relevant context while allowing sensitive data
to be stripped.
Do not copy:
- Dozens of builder options into a small internal client.
- Transport internals in the user-facing client API.
Sources:
- https://docs.rs/reqwest/latest/reqwest/
- https://docs.rs/reqwest/latest/reqwest/struct.ClientBuilder.html
- https://docs.rs/reqwest/latest/reqwest/struct.RequestBuilder.html
- https://docs.rs/reqwest/latest/reqwest/struct.Error.html
rustls style
Borrow:
- Security-critical configuration can use type-state builders when ordering
and completeness matter.
- Dangerous or verification-bypassing APIs must be explicitly named and
isolated.
- Protocol errors should be typed and non-exhaustive so new failure modes can
be added without breaking users.
Do not copy:
- Dense TLS-style state machines and type-state config for ordinary business
settings.
- Any API that silently disables verification or downgrades security.
Sources:
- https://docs.rs/rustls/latest/rustls/
- https://docs.rs/rustls/latest/rustls/struct.ConfigBuilder.html
- https://docs.rs/rustls/latest/rustls/enum.Error.html
- https://github.com/rustls/rustls/tree/main/rustls/tests
quinn / h3 style
Borrow:
- Keep deterministic sans-IO protocol core separate from socket, runtime,
timer, and task adapters.
- Split endpoint/global, connection, transport, crypto, and HTTP layer config.
- Expose protocol traits so higher layers can adapt to multiple transports.
Do not copy:
- Experimental 0.x protocol APIs as stable public API templates.
- QUIC token, congestion, MTU, and anti-replay machinery into ordinary
request/response services.
Sources:
- https://docs.rs/quinn/latest/quinn/
- https://docs.rs/quinn-proto/latest/quinn_proto/
- https://docs.rs/h3/latest/h3/
- https://docs.rs/h3-quinn/latest/h3_quinn/
Concurrency And Async Primitive Lessons
futures-rs style
Borrow:
- Separate async protocol traits (
Future,Stream,Sink) from executors,
channels, IO adapters, test utilities, and macros.
- Backpressure, flush/close, termination, waker, abort, and drop behavior are
protocol semantics, not implementation details.
Do not copy:
- A custom executor or poll/waker implementation unless the product owns the
runtime problem.
Abortableas a promise to cancel arbitrary OS or IO work.
Sources:
- https://github.com/rust-lang/futures-rs
- https://docs.rs/futures-core/latest/futures_core/
- https://docs.rs/futures-sink/latest/futures_sink/
- https://docs.rs/futures-test/latest/futures_test/
rayon style
Borrow:
- User-facing parallel iterator APIs can sit above a concentrated scheduler
core.
- Type-system and compile-fail tests should enforce
Send,Sync, lifetime,
and scoped-task invariants.
- Panic policy should be explicit at the spawn/scope boundary.
Do not copy:
- CPU work-stealing pools for IO-heavy or async workloads.
- A one-time global thread-pool model without documenting configuration limits.
Sources:
- https://docs.rs/rayon/latest/rayon/
- https://docs.rs/rayon-core/latest/rayon_core/
- https://github.com/rayon-rs/rayon/tree/main/rayon-core/src/compile_fail
crossbeam / parking_lot style
Borrow:
- Concurrency primitives should be small, composable, and not pretend to own an
application runtime.
- Unsafe memory reclamation, raw locks, park/unpark queues, scoped threads, and
channel select behavior belong behind narrow APIs with explicit contracts.
- Fairness, blocking, retry, timeout, disconnect, poisoning, and wakeup policy
must be documented as API behavior.
Do not copy:
- Lock-free epoch or raw-lock internals into business modules.
- Non-deterministic select/steal behavior without making it part of the
contract and test strategy.
Sources:
- https://docs.rs/crossbeam/latest/crossbeam/
- https://docs.rs/crossbeam-channel/latest/crossbeam_channel/
- https://docs.rs/crossbeam-epoch/latest/crossbeam_epoch/
- https://docs.rs/parking_lot/latest/parking_lot/
- https://docs.rs/lock_api/latest/lock_api/
Data, Query, And Storage Lessons
Polars style
Borrow:
- Separate dataframe/series core, lazy logical plan, optimizer/execution, IO
adapters, SQL adapter, and error taxonomy.
- Lazy execution needs a real intermediate representation and an explicit
collect or execution boundary.
Do not copy:
- Huge feature matrices, unchecked constructors, and engine-scale complexity
into ordinary data apps.
Sources:
- https://docs.pola.rs/
- https://github.com/pola-rs/polars/tree/main/crates
- https://docs.rs/polars/latest/polars/
Arrow-rs style
Borrow:
- Low-level data foundations should separate arrays, schemas, buffers, compute,
IPC, parquet, and top-level re-exports.
- Data invariants such as same-length arrays and schema/data alignment should
be encoded in core types and integration tests.
Do not copy:
dyn Arraydowncasting and unsafe data-layer complexity into business code.- A data container layer as if it were a query engine.
Sources:
- https://docs.rs/arrow/latest/arrow/
- https://docs.rs/arrow/latest/arrow/array/trait.Array.html
- https://docs.rs/arrow/latest/arrow/array/struct.RecordBatch.html
- https://arrow.apache.org/rust/arrow_integration_testing/
SQLx style
Borrow:
- Keep SQL text as a source of truth when the product team wants SQL-first
control, then add compile-time or offline validation at the boundary.
- Separate facade, core database traits, driver crates, macros, CLI, and tests.
- Runtime errors still need typed public variants even when compile-time query
checking exists.
Do not copy:
- Build-time database requirements or offline metadata unless CI and developer
workflow can support them.
- Macro-only query APIs when dynamic query building is required.
Sources:
- https://docs.rs/sqlx/latest/sqlx/
- https://docs.rs/sqlx/latest/sqlx/trait.Database.html
- https://docs.rs/sqlx/latest/sqlx/trait.Executor.html
- https://docs.rs/sqlx/latest/sqlx/macro.query.html
Diesel / SeaORM style
Borrow:
- Type-level query DSLs can make schema, backend support, selectable fields,
and row mapping compile-time concerns.
- Service-layer ORMs can be useful adapters around SQLx/SeaQuery-style dynamic
query construction when application productivity matters.
- Tests should match the boundary: compile diagnostics for type DSLs, real DB
roundtrips for drivers, and mock query logs for ORMs.
Do not copy:
- Complex type errors, heavy derive ecosystems, native linking constraints, or
ORM relation machinery unless the application explicitly needs them.
Sources:
- https://docs.diesel.rs/main/diesel/
- https://docs.diesel.rs/main/diesel/query_dsl/
- https://docs.diesel.rs/main/diesel/query_builder/trait.QueryFragment.html
- https://docs.rs/sea-orm/latest/sea_orm/
Universal Rust Design Rules
1. Pick one state ownership model before naming modules. 2. Keep core free of IO, OS handles, renderer handles, provider clients, and environment reads. 3. Make lifecycle, scheduling, backpressure, cancellation, and shutdown visible. 4. Use small traits or typed protocols for extension points. 5. Convert errors only at explicit boundaries; do not warn and silently fall back for user-visible missing behavior. 6. Observability is part of architecture: metrics, logs, queue depth, frame telemetry, cache state, or diagnostics should be externally readable. 7. Tests must be able to step the system through core behavior without the full platform stack. 8. Split crates only when the boundary is stable, reusable, independently testable, or isolates expensive dependencies and side effects. 9. Define trait protocols before adding derive macros; macros are adoption tooling, not the architecture. 10. Keep observability producer APIs separate from subscribers/exporters, and keep diagnostics facts separate from report rendering. 11. For protocols and security-sensitive systems, separate deterministic core, runtime/socket adapters, configuration scope, and dangerous APIs. 12. For concurrency, state who owns scheduling and what cancellation, close, fairness, blocking, wakeup, and panic behavior mean. 13. For data systems, separate data containers, query/planning IR, IO/backend drivers, schema validation, and runtime errors.
Architecture Foundation Spec Template
Use this template for a repo-facing architecture artifact. Keep it specific: name files, modules, APIs, validation commands, and issue/PR links when known.
Objective
State the product or engineering goal in one paragraph.
Current Evidence
| Area | Evidence | Implication |
|---|---|---|
| Entrypoints | ||
| Core models | ||
| Runtime/lifecycle | ||
| Adapters/backends | ||
| Generated/config artifacts | ||
| Errors/diagnostics | ||
| Tests/headless | ||
| Open issues/PRs |
Reference Models Considered
| Reference | Borrow | Do not copy | Source |
|---|---|---|---|
Chosen Shape
product/app
-
core/domain
-
runtime/application
-
adapters/backends
-
plugins/components
-
testing/headless
- Source Of Truth And Migration Debt
| Contract | Current source of truth | Consumers | Duplicates or forks | Action |
|---|---|---|---|---|
| Public API/schema | ||||
| Runtime/workflow state | ||||
| Billing/accounting state | ||||
| Config/resources | ||||
| Generated docs/examples |
Boundary Contracts
| Contract | Owner | Allowed dependencies | Forbidden dependencies | Tests |
|---|---|---|---|---|
| State ownership | ||||
| Lifecycle | ||||
| Events/actions | ||||
| Effects/IO | ||||
| Errors | ||||
| Config/resources | ||||
| Observability | ||||
| Compatibility/API |
Issue And PR Map
| Issue/PR | Contract served | Status | Gap or follow-up |
|---|---|---|---|
Compatibility And Deletion Plan
| Path or shim | Why it exists | Owner | Keep until | Delete or converge when |
|---|---|---|---|---|
P0/P1/P2 Roadmap
| Priority | Work | Files/modules | Done when | Verification |
|---|---|---|---|---|
| P0 | ||||
| P1 | ||||
| P2 |
Non-Goals
-
Open Questions
-
Readiness Language
Use precise claims. Prefer:
- "The architecture spec is complete enough to sequence P0 work."
- "The runtime contract is implemented for headless tests."
- "The platform adapter exists for macOS only; other platforms return explicit
unsupported errors."
Avoid:
- "Equivalent to X" without a feature matrix and fresh verification.
- "Production-ready" without tests, platform matrix, error policy, and docs.