dodil/erp-platform

templates/brick-example/README.md

brick-example — the starter brick

A working brick to copy: quotes with lines, sent and accepted. Rename it (brick_example → brick_<name>, Brick("example"), the quote_ table prefix) and replace the domain with yours. Every file shows the rule it is there for.

src/brick_example/
  domain/          the business rules — plain Python, no database, no HTTP
  application/     the use cases — each declared once, served as an API route AND an MCP tool
  infrastructure/  the tables, and the repository that loads/saves an aggregate whole
  app.py           the ASGI app: routes, /mcp, and the sign-in metadata for agents
  schema.sql       the brick's tables — every one prefixed, every one with a primary key
tests/             rules without a database; both doors without a bucket

Where things go. A rule ("a sent quote cannot change") lives in domain/. Who may do it and which rows they may see live in application/. Nothing in domain/ imports SQLAlchemy, FastAPI or MCP — that is what lets the rules run in milliseconds and be read by someone who is not a programmer.

Run it.

pip install -e '.[test]'
pytest -q                                     # no bucket needed
BUCKET=my-bucket erp-migrate --schema src/brick_example/schema.sql --brick quote=0.1.0
BUCKET=my-bucket DEV_ALLOW_ANON=1 DEV_USER_PERMISSIONS=example:quote:send,example:quote:accept \
  uvicorn brick_example.app:app                 # API at /docs, agents at /mcp

Asking another brick to act (optional). If quotes had to be emailed to the customer, the brick would not learn Gmail: it would hold SEND = CapabilitySeam("mail.send") and call it. With a mail provider in the composition the email goes out; with none, the call returns a ManualTask — the exact message a person sends by hand — and the use case stores it as a task. See "Capabilities" in the platform's BRICKS.md. Most bricks need none; this one has none.

Deployed behind the gateway with DODIL_USER_POOL=<org>/<pool>, a person connecting Claude.ai or ChatGPT to /mcp is sent to that pool to sign in, and their agent sees exactly the quotes they see.