$npx -y skills add maksimzayats/specx --skill specx-add-infrastructure-adapterAdd technical infrastructure adapters for specx core scopes. Use when implementing SQLAlchemy repositories and Alembic-backed persistence, Redis stores, HTTP/network clients, file or queue adapters, unit-of-work implementations, gateway implementations for external APIs or SDKs s
| 1 | # specx Add Infrastructure Adapter |
| 2 | |
| 3 | Use this skill whenever code talks to external systems. Read |
| 4 | `references/adapter.md` before writing adapters. |
| 5 | |
| 6 | ## Workflow |
| 7 | |
| 8 | 1. Define or reuse a repository under `repositories/` for owned persistence. |
| 9 | Repository ports inherit `BaseRepository` and mark required methods with |
| 10 | `@abstractmethod`. |
| 11 | 2. Define or reuse a gateway under `gateways/` for outbound business |
| 12 | capabilities to external systems such as OpenAI, payments, email, queues, or |
| 13 | external HTTP APIs. Gateway ports inherit `BaseGateway`, mark required |
| 14 | methods with `@abstractmethod`, declare external effects, and do not return |
| 15 | entities. |
| 16 | 3. Put concrete implementations under |
| 17 | `core/<scope>/infrastructure/<technology>/`. |
| 18 | 4. Inject external clients, session factories, Redis clients, SDK clients, or |
| 19 | project-owned client factories. Do not hide client construction inside |
| 20 | business methods. Generated HTTP adapters use `httpx2`, imported from the |
| 21 | `httpx2` namespace; do not generate new legacy `httpx` imports. |
| 22 | 5. A bounded short-lived client factory may stay beside its scope adapter. Put |
| 23 | every app-owned pooled client factory or wrapper under top-level |
| 24 | `infrastructure/<technology>/`, even with only one current consumer. |
| 25 | 6. Give long-lived app-owned infrastructure resources an explicit async |
| 26 | `close()` method; FastAPI lifecycle owns calling it on shutdown. |
| 27 | 7. Keep technical query/request code in infrastructure. |
| 28 | 8. Repositories may return entities. Gateways must not return entities; return |
| 29 | DTOs, primitives, enums, or explicit result objects. Do not return ORM |
| 30 | models or SDK response objects to core. |
| 31 | 9. Translate low-level exceptions into core exceptions only when callers need to |
| 32 | handle them. Catch narrow driver or SDK exceptions, preserve the cause, and |
| 33 | never expose raw provider messages, SQL, parameters, bodies, or URLs. |
| 34 | 10. For transactional persistence, implement an active `UnitOfWork` and a |
| 35 | `UnitOfWorkManager`; register the manager, not repositories, active UoWs, |
| 36 | or UoW providers for use-case injection. |
| 37 | 11. Register adapter bindings in private `_register_dependencies(...)` inside |
| 38 | `ioc/container.py`. Register every technical resource once at its owner |
| 39 | boundary and close that same app-scoped instance from lifecycle. |
| 40 | 12. Add focused integration tests only when the adapter has meaningful |
| 41 | project-owned behavior to protect; do not add generic CRUD or upstream |
| 42 | library tests just because an adapter file exists. |
| 43 | 13. For SQLAlchemy adapters, add or update Alembic migrations with |
| 44 | `$specx-sqlalchemy-migrations`. |
| 45 | |
| 46 | Logging is top-level runtime infrastructure, not a core-scope adapter. Put |
| 47 | stdlib logging setup in `infrastructure/logging/configurator.py` with a |
| 48 | `LoggingConfigurator` that inherits `BaseConfigurator`; do not create gateway |
| 49 | ports or injected logger bindings for it. |
| 50 | |
| 51 | For `/readyz`, implement required dependency checks as `core/health` gateway |
| 52 | adapters, for example |
| 53 | `core/health/infrastructure/sqlalchemy/readiness_check_gateway.py`, and bind |
| 54 | them to `ReadinessCheckGateway` in `ioc/container.py`. Bound every dependency |
| 55 | check with a short application timeout and return only a non-sensitive core |
| 56 | status. |
| 57 | |
| 58 | ## Code Style |
| 59 | |
| 60 | Use blank lines as logical separators in all code. Keep related statements |
| 61 | together, but separate independent setup, action, assertion, response, branch, |
| 62 | and transformation groups so long blocks stay readable. |
| 63 | |
| 64 | ## References |
| 65 | |
| 66 | - `references/adapter.md` - adapter layout, port binding, SQLAlchemy/UoW, Redis, |
| 67 | HTTP client, migration, and test patterns. |