archspec

Design specs for people and coding agents

A design spec your agents can build from and your team can actually review.

archspec replaces the design doc and the architecture diagram with one compact YAML file: systems, components, connections, data and the step-by-step flow. People review it as diagrams, a checker catches design mistakes before any code exists, and each coding agent gets a precise brief for the step it builds.

Open the playground Read the guide

Free · No sign-up · Nothing you type leaves your browser

shop.spec.yaml
components:
  customer:  { kind: person,   title: Customer }
  website:   { kind: system,   title: eCommerce Website }
  orders:    { kind: system,   title: Order Processing Engine }
  warehouse: { kind: external, title: Warehouse Partner }
connections:
  customer_to_website: { from: customer, to: website, label: places orders }
  website_to_orders:   { from: website, to: orders, label: submits orders }
  orders_to_warehouse: { from: orders, to: warehouse, label: sends picking lists }
Architecture drawn from the spec above
shopPEOPLE · CALLERSOUR SYSTEMSEXTERNAL · THIRD PARTIEScustomer_to_website: customer → website · places orders (not designed yet)website_to_orders: website → orders · submits orders (not designed yet)orders_to_warehouse: orders → warehouse · sends picking lists (not designed yet)customer (person)Customerpersonwebsite (system)eCommerce Websitesystemorders (system)Order ProcessingEnginesystemwarehouse (external)Warehouse Partnerexternalcustomer_to_website: customer → website · places orders (not designed yet)places ordersnot designed yetwebsite_to_orders: website → orders · submits orders (not designed yet)submits ordersnot designed yetorders_to_warehouse: orders → warehouse · sends picking lists (not designed yet)sends pickinglistsnot designed yetLEGENDNot designed yetSynchronous callAsynchronous messageCarries sensitive data (PII, PCI, …)Dead-letter routePersonSystemExternal partyServiceWorkerDatabaseQueueTrust zone
shopPEOPLE · CALLERSOUR SYSTEMSEXTERNAL · THIRD PARTIEScustomer_to_website: customer → website · places orders (not designed yet)website_to_orders: website → orders · submits orders (not designed yet)orders_to_warehouse: orders → warehouse · sends picking lists (not designed yet)customer (person)Customerpersonwebsite (system)eCommerce Websitesystemorders (system)Order ProcessingEnginesystemwarehouse (external)Warehouse Partnerexternalcustomer_to_website: customer → website · places orders (not designed yet)places ordersnot designed yetwebsite_to_orders: website → orders · submits orders (not designed yet)submits ordersnot designed yetorders_to_warehouse: orders → warehouse · sends picking lists (not designed yet)sends pickinglistsnot designed yetLEGENDNot designed yetSynchronous callAsynchronous messageCarries sensitive data (PII, PCI, …)Dead-letter routePersonSystemExternal partyServiceWorkerDatabaseQueueTrust zone

Spec-driven development

Structured specs instead of walls of Markdown.

Spec-driven workflows have agents write requirements, plans and task lists as pages of prose. It reads well, but it is long, nothing checks it, and reviewers end up skimming. In archspec the design is data, so it can be validated, diffed line by line, drawn as diagrams and sliced into exactly what one agent needs.

Prose specMarkdown, per feature

…and the next page. Reviewed by reading; ambiguity is found in code review.

archspeconline-shop.spec.yaml, step S6
- id: S6
  via: storefront_to_order-processing-api
  call: orders.CreateOrder
  description: Stores the order and queues it for fulfilment, in one transaction.
  errors: { ALREADY_EXISTS: returns the order already stored for that idempotency key }
  request:
    build: CreateOrderRequest
    map:
      customerId:     request.customerId
      idempotencyKey: headers.Idempotency-Key
      itemCount:      cart.item_count
      totalCents:     cart.total_cents

checked: 0 errorsdrawn at 3 levelsbrief: archspec task S6

Prose specarchspec
What reviewers readPages of text per featureA YAML diff, the diagrams and the findings
Precision"should", "usually", "a few seconds"Types, fields, ports, auth and timeouts that 33 rules check
What an agent getsThe whole document in its contextA brief for one step: its payloads, mappings, tables and errors
Feedback while draftingReview comments, after the code existsFindings with line numbers, as text, JSON or SARIF
DiagramsDrawn separately, if at allGenerated from the spec, at every level
Staying currentDrifts from the codeLives in the repo; CI checks it on every pull request
  1. Draft

    You or your agent write the YAML. Start with the business flow and add detail only where it matters.

  2. Check and review

    The checker reports mistakes with line numbers. Reviewers read the diagrams and the diff, and record decisions in the spec.

  3. Build

    Hand each agent the brief for its step: what it receives, what it writes, what it sends and how it handles errors.

  4. Keep in sync

    The spec stays next to the code. CI checks it on every pull request, so the design and the build don't drift apart.

See it work

What changes when the design is a spec.

01

Start with the business, then drill down.

Begin with people and systems, in words a business stakeholder recognises. Open a system to see the services, queues and databases inside it; open a service to see its endpoints and what it owns. Every level comes from the same file, so they never disagree.

  • One diagram per level, drawn for you
  • Lines roll up: one arrow between systems stands for every connection inside
  • Links with no design under them yet are flagged, so you see what is left to do
  • Go as deep as you need: stop at a business sketch, map the components, or specify every endpoint and payload
online-shopA customer checks out on the website; the order processing engine stores the order and starts fulfilment.INTERNET · CALLERSOUR SYSTEMSINTERNET · THIRD PARTIEScustomer_to_ecommerce-website: customer → ecommerce-website · browses and places orders customer_to_storefront: customer → storefront · HTTPS 443 · sync encryption TLS1.2+ · auth oauth2-jwt · crosses internet->dmz data: CartUpdate: What is in the customer's cart; CartSaved: The saved cart's id; CheckoutRequest: The cart the customer is checking out; CreateOrderResponse: Order id and statusecommerce-website_to_order-processing-engine: ecommerce-website → order-processing-engine · submits orders storefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statusorder-processing-engine_to_warehouse: order-processing-engine → warehouse · sends picking lists (not designed yet)customer (person) zone internetCustomerpersonecommerce-website (system) Where customers browse and check outeCommerce Websitesystem · 2 insideorder-processing-engine (system) Takes orders and starts fulfilmentOrder ProcessingEnginesystem · 4 insidewarehouse (external) zone internetWarehouse Partnerexternalcustomer_to_ecommerce-website: customer → ecommerce-website · browses and places orders customer_to_storefront: customer → storefront · HTTPS 443 · sync encryption TLS1.2+ · auth oauth2-jwt · crosses internet->dmz data: CartUpdate: What is in the customer's cart; CartSaved: The saved cart's id; CheckoutRequest: The cart the customer is checking out; CreateOrderResponse: Order id and statusbrowses andplaces ordersvia HTTPSecommerce-website_to_order-processing-engine: ecommerce-website → order-processing-engine · submits orders storefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statussubmits ordersvia gRPCorder-processing-engine_to_warehouse: order-processing-engine → warehouse · sends picking lists (not designed yet)sends pickinglistsnot designed yetLEGENDBusiness relationshipNot designed yetSynchronous callAsynchronous messageCarries sensitive data (PII, PCI, …)Dead-letter routePersonSystemHas parts insideExternal partyServiceWorkerDatabaseQueueTrust zone
online-shopA customer checks out on the website; the order processing engine stores the order and starts fulfilment.INTERNET · CALLERSOUR SYSTEMSINTERNET · THIRD PARTIEScustomer_to_ecommerce-website: customer → ecommerce-website · browses and places orders customer_to_storefront: customer → storefront · HTTPS 443 · sync encryption TLS1.2+ · auth oauth2-jwt · crosses internet->dmz data: CartUpdate: What is in the customer's cart; CartSaved: The saved cart's id; CheckoutRequest: The cart the customer is checking out; CreateOrderResponse: Order id and statusecommerce-website_to_order-processing-engine: ecommerce-website → order-processing-engine · submits orders storefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statusorder-processing-engine_to_warehouse: order-processing-engine → warehouse · sends picking lists (not designed yet)customer (person) zone internetCustomerpersonecommerce-website (system) Where customers browse and check outeCommerce Websitesystem · 2 insideorder-processing-engine (system) Takes orders and starts fulfilmentOrder ProcessingEnginesystem · 4 insidewarehouse (external) zone internetWarehouse Partnerexternalcustomer_to_ecommerce-website: customer → ecommerce-website · browses and places orders customer_to_storefront: customer → storefront · HTTPS 443 · sync encryption TLS1.2+ · auth oauth2-jwt · crosses internet->dmz data: CartUpdate: What is in the customer's cart; CartSaved: The saved cart's id; CheckoutRequest: The cart the customer is checking out; CreateOrderResponse: Order id and statusbrowses andplaces ordersvia HTTPSecommerce-website_to_order-processing-engine: ecommerce-website → order-processing-engine · submits orders storefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statussubmits ordersvia gRPCorder-processing-engine_to_warehouse: order-processing-engine → warehouse · sends picking lists (not designed yet)sends pickinglistsnot designed yetLEGENDBusiness relationshipNot designed yetSynchronous callAsynchronous messageCarries sensitive data (PII, PCI, …)Dead-letter routePersonSystemHas parts insideExternal partyServiceWorkerDatabaseQueueTrust zone
online-shop › Order Processing EngineTakes orders and starts fulfilmentOrder Processing EnginesystemOUTSIDE · CALLERSPRIVATEINTERNET · CALLEDstorefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statusoutbox-relay_to_order-events: outbox-relay → order-events · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentorder-events_to_fulfillment-worker: order-events → fulfillment-worker · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentDead-letter route: order-events → order-events-dlqorder-processing-engine_to_warehouse: order-processing-engine → warehouse · sends picking lists (not designed yet)ecommerce-website (system) Where customers browse and check outeCommerce Websitesystem · 2 insideOrder Processing Engine itself: connections not tied to a flow step yetorder-processing-api (service) owns orders_db zone privateOrder Processing APIservice · 2 insideorder-events (queue) zone privateorder-events (SQS)queueorder-events-dlq (queue) zone privateorder-events-dlq(SQS)queuefulfillment-worker (service) owns fulfillment_db zone privateFulfillment Workerservice · 1 insidewarehouse (external) zone internetWarehouse Partnerexternalstorefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statusgRPC 443PIIoutbox-relay_to_order-events: outbox-relay → order-events · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentAWS-SQS 443PIIorder-events_to_fulfillment-worker: order-events → fulfillment-worker · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentAWS-SQS 443PIIDead-letter route: order-events → order-events-dlqDLQorder-processing-engine_to_warehouse: order-processing-engine → warehouse · sends picking lists (not designed yet)sends pickinglistsnot designed yetLEGENDNot designed yetSynchronous callAsynchronous messageCarries sensitive data (PII, PCI, …)Dead-letter routeSystemHas parts insideExternal partyServiceWorkerDatabaseQueueTrust zone
online-shop › Order Processing EngineTakes orders and starts fulfilmentOrder Processing EnginesystemOUTSIDE · CALLERSPRIVATEINTERNET · CALLEDstorefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statusoutbox-relay_to_order-events: outbox-relay → order-events · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentorder-events_to_fulfillment-worker: order-events → fulfillment-worker · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentDead-letter route: order-events → order-events-dlqorder-processing-engine_to_warehouse: order-processing-engine → warehouse · sends picking lists (not designed yet)ecommerce-website (system) Where customers browse and check outeCommerce Websitesystem · 2 insideOrder Processing Engine itself: connections not tied to a flow step yetorder-processing-api (service) owns orders_db zone privateOrder Processing APIservice · 2 insideorder-events (queue) zone privateorder-events (SQS)queueorder-events-dlq (queue) zone privateorder-events-dlq(SQS)queuefulfillment-worker (service) owns fulfillment_db zone privateFulfillment Workerservice · 1 insidewarehouse (external) zone internetWarehouse Partnerexternalstorefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statusgRPC 443PIIoutbox-relay_to_order-events: outbox-relay → order-events · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentAWS-SQS 443PIIorder-events_to_fulfillment-worker: order-events → fulfillment-worker · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentAWS-SQS 443PIIDead-letter route: order-events → order-events-dlqDLQorder-processing-engine_to_warehouse: order-processing-engine → warehouse · sends picking lists (not designed yet)sends pickinglistsnot designed yetLEGENDNot designed yetSynchronous callAsynchronous messageCarries sensitive data (PII, PCI, …)Dead-letter routeSystemHas parts insideExternal partyServiceWorkerDatabaseQueueTrust zone
online-shop › Order Processing Engine › Order Processing APIInside Order Processing APIOrder Processing APIserviceOUTSIDE · CALLERSPRIVATEPRIVATE · CALLEDoutbox-relay_to_orders_db: outbox-relay → orders_db · PostgreSQL 5432 · sync encryption TLS1.2+, at rest KMS · auth iam-db-auth data: orders_db.outbox: Events waiting to be publishedoutbox-relay_to_order-events: outbox-relay → order-events · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentstorefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statusorder-processing-api_to_orders_db: order-processing-api → orders_db · PostgreSQL 5432 · sync encryption TLS1.2+, at rest KMS · auth iam-db-auth data: orders_db.orders: Orders; orders_db.outbox: Events waiting to be publishedecommerce-website (system) Where customers browse and check outeCommerce Websitesystem · 2 insideS6 in Order Processing API: S6 orders.CreateOrder (CreateOrderRequest)orders.CreateOrderS6 · endpointorders_db (database) zone privateOrders DBpostgresoutbox-relay (worker) zone privateOutbox Relayworkerorder-events (queue) zone privateorder-events (SQS)queueoutbox-relay_to_orders_db: outbox-relay → orders_db · PostgreSQL 5432 · sync encryption TLS1.2+, at rest KMS · auth iam-db-auth data: orders_db.outbox: Events waiting to be publishedPostgreSQL 5432PIIoutbox-relay_to_order-events: outbox-relay → order-events · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentAWS-SQS 443PIIstorefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statusgRPC 443PIIorder-processing-api_to_orders_db: order-processing-api → orders_db · PostgreSQL 5432 · sync encryption TLS1.2+, at rest KMS · auth iam-db-auth data: orders_db.orders: Orders; orders_db.outbox: Events waiting to be publishedPostgreSQL 5432PIILEGENDSynchronous callAsynchronous messageCarries sensitive data (PII, PCI, …)Dead-letter routeSystemHas parts insideEndpoint, handler or jobExternal partyServiceWorkerDatabaseQueueTrust zone
online-shop › Order Processing Engine › Order Processing APIInside Order Processing APIOrder Processing APIserviceOUTSIDE · CALLERSPRIVATEPRIVATE · CALLEDoutbox-relay_to_orders_db: outbox-relay → orders_db · PostgreSQL 5432 · sync encryption TLS1.2+, at rest KMS · auth iam-db-auth data: orders_db.outbox: Events waiting to be publishedoutbox-relay_to_order-events: outbox-relay → order-events · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentstorefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statusorder-processing-api_to_orders_db: order-processing-api → orders_db · PostgreSQL 5432 · sync encryption TLS1.2+, at rest KMS · auth iam-db-auth data: orders_db.orders: Orders; orders_db.outbox: Events waiting to be publishedecommerce-website (system) Where customers browse and check outeCommerce Websitesystem · 2 insideS6 in Order Processing API: S6 orders.CreateOrder (CreateOrderRequest)orders.CreateOrderS6 · endpointorders_db (database) zone privateOrders DBpostgresoutbox-relay (worker) zone privateOutbox Relayworkerorder-events (queue) zone privateorder-events (SQS)queueoutbox-relay_to_orders_db: outbox-relay → orders_db · PostgreSQL 5432 · sync encryption TLS1.2+, at rest KMS · auth iam-db-auth data: orders_db.outbox: Events waiting to be publishedPostgreSQL 5432PIIoutbox-relay_to_order-events: outbox-relay → order-events · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentAWS-SQS 443PIIstorefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statusgRPC 443PIIorder-processing-api_to_orders_db: order-processing-api → orders_db · PostgreSQL 5432 · sync encryption TLS1.2+, at rest KMS · auth iam-db-auth data: orders_db.orders: Orders; orders_db.outbox: Events waiting to be publishedPostgreSQL 5432PIILEGENDSynchronous callAsynchronous messageCarries sensitive data (PII, PCI, …)Dead-letter routeSystemHas parts insideEndpoint, handler or jobExternal partyServiceWorkerDatabaseQueueTrust zone

The business view: who uses which system.

02

One file, every view your reviewers ask for.

Architects get diagrams, security gets the ports-and-protocols matrix with data sensitivity, developers get an API reference and DDL, and coding agents get a brief for the one step they are building. All generated, all in sync.

  • Export SVG, PNG, Markdown, CSV, OpenAPI, Mermaid and LikeC4
  • Briefs carry exactly the payloads, mappings and tables a step needs
online-shop › Order Processing EngineTakes orders and starts fulfilmentOrder Processing EnginesystemOUTSIDE · CALLERSPRIVATEINTERNET · CALLEDstorefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statusoutbox-relay_to_order-events: outbox-relay → order-events · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentorder-events_to_fulfillment-worker: order-events → fulfillment-worker · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentDead-letter route: order-events → order-events-dlqorder-processing-engine_to_warehouse: order-processing-engine → warehouse · sends picking lists (not designed yet)ecommerce-website (system) Where customers browse and check outeCommerce Websitesystem · 2 insideOrder Processing Engine itself: connections not tied to a flow step yetorder-processing-api (service) owns orders_db zone privateOrder Processing APIservice · 2 insideorder-events (queue) zone privateorder-events (SQS)queueorder-events-dlq (queue) zone privateorder-events-dlq(SQS)queuefulfillment-worker (service) owns fulfillment_db zone privateFulfillment Workerservice · 1 insidewarehouse (external) zone internetWarehouse Partnerexternalstorefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statusgRPC 443PIIoutbox-relay_to_order-events: outbox-relay → order-events · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentAWS-SQS 443PIIorder-events_to_fulfillment-worker: order-events → fulfillment-worker · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentAWS-SQS 443PIIDead-letter route: order-events → order-events-dlqDLQorder-processing-engine_to_warehouse: order-processing-engine → warehouse · sends picking lists (not designed yet)sends pickinglistsnot designed yetLEGENDNot designed yetSynchronous callAsynchronous messageCarries sensitive data (PII, PCI, …)Dead-letter routeSystemHas parts insideExternal partyServiceWorkerDatabaseQueueTrust zone
online-shop › Order Processing EngineTakes orders and starts fulfilmentOrder Processing EnginesystemOUTSIDE · CALLERSPRIVATEINTERNET · CALLEDstorefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statusoutbox-relay_to_order-events: outbox-relay → order-events · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentorder-events_to_fulfillment-worker: order-events → fulfillment-worker · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentDead-letter route: order-events → order-events-dlqorder-processing-engine_to_warehouse: order-processing-engine → warehouse · sends picking lists (not designed yet)ecommerce-website (system) Where customers browse and check outeCommerce Websitesystem · 2 insideOrder Processing Engine itself: connections not tied to a flow step yetorder-processing-api (service) owns orders_db zone privateOrder Processing APIservice · 2 insideorder-events (queue) zone privateorder-events (SQS)queueorder-events-dlq (queue) zone privateorder-events-dlq(SQS)queuefulfillment-worker (service) owns fulfillment_db zone privateFulfillment Workerservice · 1 insidewarehouse (external) zone internetWarehouse Partnerexternalstorefront_to_order-processing-api: storefront → order-processing-api · gRPC 443 · sync encryption TLS1.3 mTLS · auth mtls-identity · crosses dmz->private data: CreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and statusgRPC 443PIIoutbox-relay_to_order-events: outbox-relay → order-events · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentAWS-SQS 443PIIorder-events_to_fulfillment-worker: order-events → fulfillment-worker · AWS-SQS 443 · async / at-least-once encryption TLS1.2+, at rest SSE-KMS · auth iam-role data: OrderPlacedEvent: Placed order, for fulfilmentAWS-SQS 443PIIDead-letter route: order-events → order-events-dlqDLQorder-processing-engine_to_warehouse: order-processing-engine → warehouse · sends picking lists (not designed yet)sends pickinglistsnot designed yetLEGENDNot designed yetSynchronous callAsynchronous messageCarries sensitive data (PII, PCI, …)Dead-letter routeSystemHas parts insideExternal partyServiceWorkerDatabaseQueueTrust zone
online-shop › Order Processing Engine: sequenceSteps involving Order Processing Engineecommerce-website (system)eCommerce Websiteorder-processing-engine (system)Order ProcessingEnginewarehouse (external)Warehouse Partnerorder-processing-api (service)Order Processing APIorder-events (queue)order-events (SQS)fulfillment-worker (service)Fulfillment WorkerRequest · eCommerce Website calls orders.CreateOrderS6 via storefront_to_order-processing-api: ecommerce-website → order-processing-api carries PII dataS6 orders.CreateOrder (CreateOrderRequest)S8 via storefront_to_order-processing-api: order-processing-api → ecommerce-websiteS8 200 CreateOrderResponseScheduled · Outbox Relay polls outbox every 1sS11 via outbox-relay_to_order-events: order-processing-api → order-events carries PII dataS11 publish OrderPlacedEventMessage · Fulfillment Worker receives OrderPlacedEventS13 via order-events_to_fulfillment-worker: order-events → fulfillment-worker carries PII dataS13 deliver OrderPlacedEventon_error: leave the message on thequeue; SQS redelivers it, then movesit to the DLQ after 5 receiveson_unknown_schema_version: send tothe DLQ without processingFrom the architecture · not in the flow yetorder-processing-engine_to_warehouse: order-processing-engine → warehouse, a business link with no design under it yetsends picking listsLEGENDBusiness link, not designed yetSteps inside one box (open it to see them)Synchronous call or DB statementResponseAsynchronous messageCarries sensitive data (PII, PCI, …)Error handling / conflict ruleNew trigger (separate execution)
online-shop › Order Processing Engine: sequenceSteps involving Order Processing Engineecommerce-website (system)eCommerce Websiteorder-processing-engine (system)Order ProcessingEnginewarehouse (external)Warehouse Partnerorder-processing-api (service)Order Processing APIorder-events (queue)order-events (SQS)fulfillment-worker (service)Fulfillment WorkerRequest · eCommerce Website calls orders.CreateOrderS6 via storefront_to_order-processing-api: ecommerce-website → order-processing-api carries PII dataS6 orders.CreateOrder (CreateOrderRequest)S8 via storefront_to_order-processing-api: order-processing-api → ecommerce-websiteS8 200 CreateOrderResponseScheduled · Outbox Relay polls outbox every 1sS11 via outbox-relay_to_order-events: order-processing-api → order-events carries PII dataS11 publish OrderPlacedEventMessage · Fulfillment Worker receives OrderPlacedEventS13 via order-events_to_fulfillment-worker: order-events → fulfillment-worker carries PII dataS13 deliver OrderPlacedEventon_error: leave the message on thequeue; SQS redelivers it, then movesit to the DLQ after 5 receiveson_unknown_schema_version: send tothe DLQ without processingFrom the architecture · not in the flow yetorder-processing-engine_to_warehouse: order-processing-engine → warehouse, a business link with no design under it yetsends picking listsLEGENDBusiness link, not designed yetSteps inside one box (open it to see them)Synchronous call or DB statementResponseAsynchronous messageCarries sensitive data (PII, PCI, …)Error handling / conflict ruleNew trigger (separate execution)
ConnFrom → ToDirectionModeProtocolPortIn transitAt restAuthBoundaryTimeoutData
customer_to_storefrontcustomer → storefrontinboundsyncHTTPS443TLS1.2+—oauth2-jwtinternet->dmz5sCartUpdate: What is in the customer's cart; CartSaved: The saved cart's id; CheckoutRequest: The cart the customer is checking out; CreateOrderResponse: Order id and status [PII]
storefront_to_carts_dbstorefront → carts_dbinternalsyncRedis6379TLS1.2+KMSauth-tokendmz->private50mscarts_db.carts: Open carts, kept for 7 days [PII]
storefront_to_order-processing-apistorefront → order-processing-apiinternalsyncgRPC443TLS1.3 mTLS—mtls-identitydmz->private2sCreateOrderRequest: Order built from the cart; CreateOrderResponse: Order id and status [PII]
order-processing-api_to_orders_dborder-processing-api → orders_dbinternalsyncPostgreSQL5432TLS1.2+KMSiam-db-auth—2sorders_db.orders: Orders; orders_db.outbox: Events waiting to be published [PII]
outbox-relay_to_orders_dboutbox-relay → orders_dbinternalsyncPostgreSQL5432TLS1.2+KMSiam-db-auth—2sorders_db.outbox: Events waiting to be published [PII]
outbox-relay_to_order-eventsoutbox-relay → order-eventsinternalasync / at-least-onceAWS-SQS443TLS1.2+SSE-KMSiam-role——OrderPlacedEvent: Placed order, for fulfilment [PII]
order-events_to_fulfillment-workerorder-events → fulfillment-workerinternalasync / at-least-onceAWS-SQS443TLS1.2+SSE-KMSiam-role—30sOrderPlacedEvent: Placed order, for fulfilment [PII]
fulfillment-worker_to_fulfillment_dbfulfillment-worker → fulfillment_dbinternalsyncPostgreSQL5432TLS1.2+KMSsecrets-manager—2sfulfillment_db.processed_events: Dedupe keys for consumed events; fulfillment_db.shipments: Shipments to pick and pack [PII]

Storefront API (storefront)

PUT /cart (S1)

Saves the customer's cart, replacing what was there.

  • Called by customer via customer_to_storefront: HTTPS 443, auth oauth2-jwt, crosses internet->dmz, timeout 5s

Request:

CartUpdate: What is in the customer's cart

Field Type Required Rules Data Description
cartId uuid yes Chosen by the browser when the cart is first saved
customerId uuid yes PII The signed-in customer
itemCount int yes min 0 Number of items; 0 empties the cart
totalCents int yes min 0 Cart total in cents

Response 200:

CartSaved: The saved cart's id

Field Type Required Rules Data Description
cartId uuid yes
  • Error 401: missing or expired token
  • Error 422: itemCount or totalCents is negative

Implementation: S2 TX: INSERT carts

POST /checkout (S4)

Turns the saved cart into an order. Safe to retry with the same Idempotency-Key.

  • Called by customer via customer_to_storefront: HTTPS 443, auth oauth2-jwt, crosses internet->dmz, timeout 5s
  • Header Idempotency-Key: required

Request:

CheckoutRequest: The cart the customer is checking out

Field Type Required Rules Data Description
cartId uuid yes The cart saved with PUT /cart
customerId uuid yes PII Must match the token's subject

Response 201:

CreateOrderResponse: Order id and status

Field Type Required Rules Data Description
orderId uuid yes Use it to track the order
status string yes one of PLACED
  • Error 401: missing or expired token
  • Error 404: no saved cart with that id
  • Error 409: the Idempotency-Key was used for a different cart

Implementation: S5 TX: SELECT carts; S6 orders.CreateOrder (CreateOrderRequest)

Calls

  • order-processing-api: orders.CreateOrder (S6 via storefront_to_order-processing-api) with CreateOrderRequest
# Task: implement S6 of `online-shop`

You are implementing part of the system described in `online-shop.spec.yaml`. That spec is the source of truth:
do not change contracts, tables or connections in code. If the spec looks wrong or incomplete, stop and
propose a change to the spec instead of working around it.

**Component(s) you are changing:** storefront

## Steps to implement

```yaml
- id: S6
  via: storefront_to_order-processing-api
  call: orders.CreateOrder
  description: Stores the order and queues it for fulfilment, in one transaction.
  errors:
    ALREADY_EXISTS: returns the order already stored for that idempotency key
  request:
    build: CreateOrderRequest
    map:
      customerId: request.customerId
      idempotencyKey: headers.Idempotency-Key
      itemCount: cart.item_count
      totalCents: cart.total_cents
```

## Surrounding steps (context only; already implemented elsewhere)

```yaml
- id: S4
  via: customer_to_storefront
  call: POST /checkout
  description: Turns the saved cart into an order. Safe to retry with the same Idempotency-Key.
  headers:
    Idempotency-Key: required
  request: CheckoutRequest
  errors:
    "401": missing or expired token
    "404": no saved cart with that id
    "409": the Idempotency-Key was used for a different cart
- id: S5
  via: storefront_to_carts_db
  transaction:
    - select: carts_db.carts
      as: cart
      where: id = request.cartId
- id: S7
  via: order-processing-api_to_orders_db
  transaction:
    - insert: orders_db.orders
      as: order
      map:
        id: $uuid
        customer_id: request.customerId
        status: "'PLACED'"
        item_count: request.itemCount
        total_cents: request.totalCents
        idempotency_key: request.idempotencyKey
      on_conflict:
        idempotency_key: return the existing order
    - insert: orders_db.outbox
      as: outbox
      map:
        id: $uuid
        aggregate_id: order.id
        event_type: "'order.placed'"
        payload:
          build: OrderPlacedEvent
          map:
            eventId: outbox.id
            eventType: "'order.placed'"
            schemaVersion: "1"
            orderId: order.id
            customerId: order.customer_id
            itemCount: order.item_count
- id: S8
  via: storefront_to_order-processing-api
  respond:
    status: 200
    body:
      build: CreateOrderResponse
      map:
        orderId: order.id
        status: order.status
- id: S9
  via: customer_to_storefront
  respond:
    status: 201
    body: CreateOrderResponse
```

## Connections

```yaml
storefront_to_order-processing-api:
  from: storefront
  to: order-processing-api
  type: internal-grpc
  auth: mtls-identity
  timeout: 2s
  deadlinePropagation: true
  carries:
    - CreateOrderRequest
    - CreateOrderResponse
customer_to_storefront:
  from: customer
  to: storefront
  type: https-rest
  auth: oauth2-jwt
  boundary: internet->dmz
  edgeProtection: WAF managed rules, 20 req/s per customer
  timeout: 5s
  retryPolicy: client retries with the same Idempotency-Key
  carries:
    - CartUpdate
    - CartSaved
    - CheckoutRequest
    - CreateOrderResponse
storefront_to_carts_db:
  from: storefront
  to: carts_db
  type: redis
  auth: auth-token
  timeout: 50ms
order-processing-api_to_orders_db:
  from: order-processing-api
  to: orders_db
  type: postgres
  auth: iam-db-auth
  statementTimeout: 2s
  connectionPool: 20
```

Connection types (platform standards):

```yaml
https-rest:
  mode: sync
  protocol: HTTPS
  port: 443
  encryption:
    inTransit: TLS1.2+
  auth:
    - oauth2-jwt
    - api-key
  requires:
    - timeout
    - retryPolicy
internal-grpc:
  mode: sync
  protocol: gRPC
  port: 443
  encryption:
    inTransit: TLS1.3
    mTLS: true
  auth:
    - mtls-identity
  requires:
    - timeout
    - deadlinePropagation
postgres:
  mode: sync
  protocol: PostgreSQL
  port: 5432
  encryption:
    inTransit: TLS1.2+
    atRest: KMS
  auth:
    - iam-db-auth
    - secrets-manager
  requires:
    - statementTimeout
    - connectionPool
redis:
  mode: sync
  protocol: Redis
  port: 6379
  encryption:
    inTransit: TLS1.2+
    atRest: KMS
  auth:
    - iam-auth
    - auth-token
  requires:
    - timeout
```

## Payload types

```yaml
CreateOrderRequest:
  description: Order built from the cart
  fields:
    customerId:
      type: uuid
      pii: true
    idempotencyKey:
      type: string
    itemCount:
      type: int
      min: 1
    totalCents:
      type: int
      min: 0
CreateOrderResponse:
  description: Order id and status
  fields:
    orderId:
      type: uuid
      description: Use it to track the order
    status:
      type: string
      enum:
        - PLACED
CartUpdate:
  description: What is in the customer's cart
  fields:
    cartId:
      type: uuid
      description: Chosen by the browser when the cart is first saved
    customerId:
      type: uuid
      pii: true
      description: The signed-in customer
    itemCount:
      type: int
      min: 0
      description: Number of items; 0 empties the cart
    totalCents:
      type: int
      min: 0
      description: Cart total in cents
      tax included: null
CartSaved:
  description: The saved cart's id
  fields:
    cartId:
      type: uuid
CheckoutRequest:
  description: The cart the customer is checking out
  fields:
    cartId:
      type: uuid
      description: The cart saved with PUT /cart
    customerId:
      type: uuid
      pii: true
      description: Must match the token's subject
OrderPlacedEvent:
  description: Placed order, for fulfilment
  classification: confidential
  fields:
    eventId:
      type: uuid
    eventType:
      type: string
      const: order.placed
    schemaVersion:
      type: int
      const: 1
    orderId:
      type: uuid
    customerId:
      type: uuid
      pii: true
    itemCount:
      type: int
```

## Tables

```yaml
carts_db.carts:
  description: Open carts, kept for 7 days
  columns:
    id:
      type: uuid
      pk: true
    customer_id:
      type: uuid
      pii: true
    item_count:
      type: int
    total_cents:
      type: bigint
orders_db.orders:
  description: Orders
  columns:
    id:
      type: uuid
      pk: true
    customer_id:
      type: uuid
      pii: true
    status:
      type: text
      enum:
        - PLACED
        - CANCELLED
    item_count:
      type: int
    total_cents:
      type: bigint
    idempotency_key:
      type: text
      unique: true
    created_at:
      type: timestamptz
      default: now()
orders_db.outbox:
  description: Events waiting to be published
  columns:
    id:
      type: uuid
      pk: true
    aggregate_id:
      type: uuid
    event_type:
      type: text
    payload:
      type: jsonb
      schema: OrderPlacedEvent
    created_at:
      type: timestamptz
      default: now()
    published_at:
      type: timestamptz
      nullable: true
```

## Invariants that must hold

- one checkout creates at most one order, even when the customer retries
- every orders row has exactly one outbox row (written in the same transaction)
- at most one shipment per order_id, even with duplicate SQS delivery

## Policies that apply

- **P2**: Connections crossing a trust boundary must authenticate
- **P5**: A flow step's payload must be listed in its connection's `carries`
- **P6**: Downstream sync timeouts must fit within the entry point's timeout
- **TYP002**: Mapping sources must be existing fields of the payload in scope
- **TYP003**: Mapped source and target types must be compatible

## Acceptance scenarios (write one test per scenario)

- [ ] **happy path**: when the customer checks out a cart with 2 items → 201 with orderId; 1 orders row; 1 outbox row then published_at set; 1 PENDING shipment with item_count 2
- [ ] **customer retries checkout**: when the same checkout is sent twice with the same Idempotency-Key → same orderId returned both times; 1 orders row; 1 outbox row

## Definition of done

- Every mapping is implemented exactly as specified (field names, types, enum values, on_conflict behaviour).
- Each acceptance scenario has an automated test. Use real dependencies in containers (e.g. Testcontainers for Postgres, LocalStack for SQS); don't mock the database or queue.
- The error-handling paths in the steps (`on_error`, `on_conflict`, `on_unknown_schema_version`) are tested.
- `archspec check online-shop.spec.yaml` still passes with no new errors.
-- Generated by archspec from online-shop.spec.yaml. Do not edit; change the spec instead.

CREATE SCHEMA IF NOT EXISTS carts_db;
CREATE SCHEMA IF NOT EXISTS fulfillment_db;
CREATE SCHEMA IF NOT EXISTS orders_db;

CREATE TABLE carts_db.carts (
  id UUID PRIMARY KEY,
  customer_id UUID NOT NULL,
  item_count INT NOT NULL,
  total_cents BIGINT NOT NULL
);
COMMENT ON COLUMN carts_db.carts.customer_id IS 'PII';

CREATE TABLE orders_db.orders (
  id UUID PRIMARY KEY,
  customer_id UUID NOT NULL,
  status TEXT NOT NULL CHECK (status IN ('PLACED', 'CANCELLED')),
  item_count INT NOT NULL,
  total_cents BIGINT NOT NULL,
  idempotency_key TEXT NOT NULL UNIQUE,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
COMMENT ON COLUMN orders_db.orders.customer_id IS 'PII';

CREATE TABLE orders_db.outbox (
  id UUID PRIMARY KEY,
  aggregate_id UUID NOT NULL,
  event_type TEXT NOT NULL,
  payload JSONB NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  published_at TIMESTAMPTZ
);
COMMENT ON COLUMN orders_db.outbox.payload IS 'schema: OrderPlacedEvent';

CREATE TABLE fulfillment_db.shipments (
  id UUID PRIMARY KEY,
  order_id UUID NOT NULL UNIQUE,
  customer_id UUID NOT NULL,
  item_count INT NOT NULL,
  status TEXT NOT NULL CHECK (status IN ('PENDING', 'SHIPPED')),
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
COMMENT ON COLUMN fulfillment_db.shipments.customer_id IS 'PII';

CREATE TABLE fulfillment_db.processed_events (
  event_id UUID PRIMARY KEY,
  processed_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

03

Mistakes show up while you type, not in development.

Someone takes a shortcut: the fulfillment worker reads the orders database directly. On a whiteboard that is one more arrow. In archspec it is three errors, each pointing at the line to fix, before a single line of code is written.

  • Ownership, encryption, auth, timeouts, dual writes, call cycles
  • Type-checked field mappings between payloads and tables
  • The same checks run in CI on every pull request
online-shop.spec.yaml
98    to: fulfillment-worker99    type: sqs-standard100    auth: iam-role101    encryption: { atRest: SSE-KMS }102    dlq: order-events-dlq103    maxReceiveCount: 5104    visibilityTimeout: 30s105    idempotentConsumer: fulfillment_db.processed_events106    carries: [OrderPlacedEvent]107108109110111112113108  fulfillment-worker_to_fulfillment_db:109    from: fulfillment-worker110    to: fulfillment_db111    type: postgres
No errors 1 info
  • iDES001order-processing-engine_to_warehouse (order-processing-engine → warehouse: sends picking lists) is a high-level link with no technical design under it yet
3 errors
  • ✗P3fulfillment-worker_to_orders_db (postgres) is missing required statementTimeout, connectionPool
  • ✗P7fulfillment-worker_to_orders_db: fulfillment-worker accesses orders_db, which is owned by order-processing-api; go through the owner's API or events
  • ✗P11fulfillment-worker_to_orders_db: auth 'password' is not allowed for postgres (allowed: iam-db-auth, secrets-manager)

A clean design: no errors.

Why

A picture can't be wrong. A spec can.

Visio, draw.io and Mermaid draw pictures, and design docs describe them in prose. You can't drill from the business view into a service's contract, and the drawing won't notice that card numbers cross the internet unencrypted, that two services write the same database, or that a timeout is shorter than the calls behind it. Those mistakes turn up in code review, in testing or in production.

archspec treats the design as code. One file says who uses which systems, what runs inside them, how they connect, what data moves and in which order. Because it is precise, it can be checked, and every view is generated from it, so the diagrams never drift from the spec.

api.spec.yaml
components:
  web:  { kind: external, title: Web App, zone: internet }
  api:  { kind: service, title: API, zone: dmz }
  data: { kind: database, title: Data, zone: private }
connections:
  web_to_api: { from: web, to: api, type: https-rest, timeout: 3s, retryPolicy: none }
  api_to_data: { from: api, to: data, type: postgres, auth: password, statementTimeout: 1s }
Findings
  • ✗P2web_to_api crosses trust boundary internet->dmz without authentication
  • ✗NET003web_to_api is a public endpoint (web -> api) but documents no edgeProtection (WAF, rate limiting, captcha)
  • ✗P11api_to_data: auth 'password' is not allowed for postgres (allowed: iam-db-auth, secrets-manager)
  • ✗P3api_to_data (postgres) is missing required connectionPool
  • ✗P7api_to_data: api accesses data, which is owned by nobody; go through the owner's API or events

What you get from one file

Every view your reviewers need, generated and kept in sync.

Checks like a static analyzer

33 rules type-check field mappings and catch unencrypted personal data, dual writes, missing timeouts, synchronous call cycles, unowned database access and untested steps, each with the line to fix.

Diagrams you can edit

Architecture and sequence diagrams drawn natively, with a legend. Add boxes, connections and steps on the diagram: archspec writes them into the YAML and keeps your comments.

Business view first

Start with people and systems joined by plain-language links. Open a system to design its services, queues and databases; open a service to see its endpoints and payloads.

Security review built in

A ports-and-protocols matrix with direction, encryption, auth and the sensitivity of the data on every connection (PII, PCI, PHI), and a table of every trust-boundary crossing.

API reference and OpenAPI

A Swagger-style reference for any box: endpoints, payloads, responses, errors, message handlers and the calls it makes. Download OpenAPI 3.1 for each service.

Briefs for coding agents

Slice the spec into the exact brief a developer or coding agent needs to build one step: the payloads, mappings, tables and error handling, and nothing else.

Reviews live in the spec

Mark a finding reviewed, or done with a comment. The review is written into the file, so it is versioned and discussed in the same pull request as the design.

Exports

SVG and PNG diagrams, Markdown and CSV security tables, Postgres DDL, Mermaid, LikeC4 and a design doc. The spec itself is plain YAML you keep next to the code.

Private by design

Your architecture never leaves your machine.

The playground is a single page with the engine, the rule pack and the guide built in. After it loads it makes no network requests at all, and a Content-Security-Policy that blocks every outbound connection makes the browser hold it to that.

  • No account, no server, no analytics
  • Work is kept in your browser between visits
  • Open and save .spec.yaml files on your own computer
  • Keeps working offline once loaded

In your pipeline

The same engine checks every pull request.

Keep specs next to the code. The command line checks them in CI with text, JSON or SARIF output, so findings appear as annotations on the pull request, and renders every diagram and table for your docs.

$ archspec check orders.spec.yaml✗ NET003  orders.spec.yaml:27 client_to_orders-api is a public endpoint (client -> orders-api) but documents no edgeProtection (WAF, rate limiting, captcha)✗ P9      orders.spec.yaml:53 synchronous call cycle: orders-api -> inventory-api -> orders-api (via orders-api_to_inventory-api, inventory-api_to_orders-api)✗ P1      orders.spec.yaml:62 orders-api_to_order-events carries PII data (OrderPlacedEvent) into storage but encryption.atRest is not set (options: SSE-SQS, SSE-KMS)✗ P8      orders.spec.yaml:175 S2a: orders-api writes to the DB (S2) and publishes directly in the same request; a crash between them loses or invents events. Write to an outbox table in the same transaction and relay it… 17 more · exit code 1

A VS Code extension with the same diagnostics, preview and visual editor is planned.

Who it's for

One source of truth, read the way each person needs it.

Architects

Design end to end, drill into contracts, and find the gaps before anything is built.

Business stakeholders

See who uses which system and what passes between them, without the technical detail.

Developers

Get an unambiguous contract for each step: payloads, mappings, tables and error handling.

Security reviewers

Every connection with port, protocol, encryption, auth, trust boundary and data sensitivity.

Coding agents

A spec that is code only: easy to parse, slice and validate, with a brief per step.

Platform teams

Own the shared catalogs: approved connection types, vendors, data labels and the rule pack.

Try it on your own system.

The playground opens with a complete example. Change it, break it, and watch the findings.

Open the playgroundStart with the business flow