

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
123456# Hermes API - Database Layer Rules78## SQLAlchemy Async Patterns910### Session Management11- Always use async sessions: `AsyncSession`12- Get sessions via dependency injection: `get_database_session()`13- Never create sessions directly - use the session factory14- Sessions are automatically committed/rolled back by FastAPI1516Example:17```python18from sqlalchemy.ext.asyncio import AsyncSession19from app.db.session import get_database_session2021async def my_endpoint(22 db: AsyncSession = Depends(get_database_session)23):24 # Use db session25 pass26```2728### Queries29- Use async query methods: `execute()`, `scalar()`, `scalars()`30- Always `await` database operations31- Use `select()` for queries, not legacy query API3233Example:34```python35from sqlalchemy import select36from app.db.models import User3738result = await session.execute(39 select(User).where(User.username == username)40)41user = result.scalar_one_or_none()42```4344## Repository Pattern4546### Structure47- Define repositories in `app/db/repositories.py`48- Each model should have a corresponding repository class49- Repositories encapsulate data access logic50- Keep business logic out of repositories5152### Repository Methods53- Use descriptive method names: `get_by_id()`, `create()`, `update()`, `delete()`54- Return model instances or None (not query objects)55- Handle exceptions at repository level56- Use type hints for all parameters and returns5758Example:59```python60class UserRepository:61 def __init__(self, session: AsyncSession):62 self.session = session6364 async def get_by_id(self, user_id: str) -> Optional[User]:65 result = await self.session.execute(66 select(User).where(User.id == user_id)67 )68 return result.scalar_one_or_none()6970 async def create(self, user_data: dict) -> User:71 user = User(**user_data)72 self.session.add(user)73 await self.session.flush()74 return user75```7677### Repository Access78- Access repositories via `get_repositories()` function79- Returns dictionary of repository instances80- Repositories share the same session8182```python83from app.db.repositories import get_repositories8485repos = await get_repositories()86user = await repos["users"].get_by_id(user_id)87```8889## Models9091### Model Definition92- Define models in `app/db/models.py`93- Inherit from declarative base defined in `app/db/base.py`94- Use type hints in column definitions95- Include `__tablename__` attribute9697### Column Definitions98- Use appropriate SQLAlchemy types99- Set `nullable=False` for required fields100- Define `default` or `server_default` for defaults101- Use `index=True` for frequently queried columns102103### Relationships104- Define relationships using `relationship()`105- Use `back_populates` for bidirectional relationships106- Use `lazy="selectin"` for async loading107- Consider cascade delete behavior108109Example:110```python111from sqlalchemy.orm import Mapped, mapped_column, relationship112from datetime import datetime113from typing import Optional114115class User(Base):116 __tablename__ = "users"117118 id: Mapped[str] = mapped_column(primary_key=True)119 username: Mapped[str] = mapped_column(unique=True, index=True)120 email: Mapped[Optional[str]] = mapped_column(nullable=True)121 created_at: Mapped[datetime] = mapped_column(default=datetime.utcnow)122123 # Relationships124 downloads: Mapped[list["Download"]] = relationship(125 back_populates="user",126 lazy="selectin"127 )128```129130## Migrations (Alembic)131132### Creating Migrations133- Use Alembic for schema migrations134- Configuration in `alembic.ini`135- Migration scripts in `migrations/versions/`136- Use descriptive migration messages137138### Migration Commands139```bash140# Create new migration141alembic revision --autogenerate -m "Add user table"142143# Apply migrations144alembic upgrade head145146# Rollback migration147alembic downgrade -1148```149150### Migration Best Practices151- Review auto-generated migrations before applying152- Test migrations in development first153- Include both upgrade and downgrade paths154- Add data migrations when needed155- Never modify applied migrations156157## Database Configuration158159### Connection Settings160- Configure database URL in `app/core/config.py`161- Use async SQLite driver: `aiosqlite`162- Connection string format: `sqlite+aiosqlite:///./data/hermes.db`163164### Session Configuration165- Pool settings configured in `app/db/session.py`166- Echo SQL in development (for debugging)167- Disable echo in production168169## Transactions170171### Transaction Boundaries172- FastAPI handles transactions automatically173- Manual transaction control when needed:174175```python176async with session.begin():177 # Multiple operations in one transaction178 user = await repos["users"].create(user_data)179 await repos["api_keys"].create(api_key_data)180```181182### Error Handling183- SQLAlchemy exceptions should be caught and converted to HTTP exceptions184- Rollback happens automatically on exceptions185- Log database errors with context186187## Testing188189### Test Database190- Use separate database for tests191- Reset database state between tests192- Use fixtures for common test data193194### Repository Testing195- Test each repository method independently196- Mock external dependencies197- Verify database state after operations198- Test error conditions199
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| TechSquidTV/Hermes.cursor/rules/30-tests.mdc · 46 | Cursor rules | buildteststylearch+4 | 85/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 46 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-app.mdc · 46 | Cursor rules | lint-formatstylearchtypes+5 | 88/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-api.mdc · 46 | Cursor rules | stylearchdependenciesapi+2 | 77/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 46 | Cursor rules | teststyletesting-strategysecurity+3 | 97/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-app-components.mdc · 46 | Cursor rules | archtypesuiperformance+1 | 65/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-app-routes.mdc · 46 | Cursor rules | archapiuido-not | 65/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/30-docker.mdc · 46 | Cursor rules | setupbuildstylesecurity+4 | 84/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/00-project.mdc · 46 | Cursor rules | setuplint-formatstylearch+4 | 89/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-app-hooks.mdc · 46 | Cursor rules | lint-formatstylearchtypes+3 | 73/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/30-docs.mdc · 46 | Cursor rules | setuplint-formatstylearch+3 | 81/100 | 14 days ago |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126 | Cursor rules | setupbuildtestlint-format+6 | 100/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 46 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 14 days ago | |
| Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| markstev/mark-starter.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+6 | 99/100 | 14 days ago | |
| langflow-ai/langflow.cursor/rules/docs_development.mdc · 153k | Cursor rules | setupbuildtestlint-format+7 | 97/100 | 14 days ago | |
| bybren-llc/safe-agentic-workflow.cursor/rules/10-backend-python.mdc · 399 | Cursor rules | testlint-formatstylegit+4 | 97/100 | today |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/techsquidtv-hermes-cursor-rules-20-hermes-api-db)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.