Sub-architect Backend. Invocado por /architect orchestrator. Lee 01-spec.md + (02-design-ui.md si mixed) + story YAML. Produce 03-arch-be.md con: endpoints, DTOs Pydantic, SQLA models, migrations idempotent, services, repositories, tests requeridos, cross-cutting (tenant isolation, currency, master-data, PII). Cross-module audit obligatorio. Activa cuando /architect spawna o user dice: '/architect-be', 'arq backend', 'diseña BE'.
72
89%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Owner:
03-arch-be.md. Diseño técnico capa BE. Output → /architect orchestrator.
backend-expert — DDD, conventions, anti-patternstessl__fastapi — async, response_model, DItessl__pytest-api-testing — async client, fixturestessl__graceful-degradation — timeout/fallbackbrand-expert, offer-expert, metrics-expert, etc.)Antes de diseñar nueva infraestructura, grep cross-codebase:
# Subsystem keywords del story
grep -rn "<kw>" backend/src/core/
grep -rn "<kw>" backend/src/shared/
grep -rn "from src.core.config\|from src.shared" backend/src/modules/{m}/
find backend/src -name "*.py" -path "*<kw>*" -o -path "*provider*" -o -path "*adapter*"Decisión:
Cita paths + lines en 03-arch-be.md § Existing systems audit.
Seguir template docs/specs/templates/03-arch-template.md con surface=BE. Llenar:
Endpoints:
| Method | Path | Auth | DTO | response_model | Notas |
|---|
Reglas:
/api/v1/{module}/...redirect_slashes=False (verificar en main.py)Bearer + X-Tenant-ID mandatory (excepto /health, /webhooks/{provider})response_model= MANDATORY (PII allowlist)DTOs:
class CreateXRequest(BaseModel):
field: str
model_config = ConfigDict(...)
class XResponse(BaseModel):
id: UUID
currency: str | None = None # si monetary
model_config = ConfigDict(from_attributes=True)Domain:
@dataclass(frozen=True)
class X:
id: UUID
tenant_id: UUID # ALWAYS
deleted_at: datetime | None # soft delete
...SQLA models:
class XModel(Base):
__tablename__ = "{module}_{plural}"
id: Mapped[UUID] = mapped_column(primary_key=True)
tenant_id: Mapped[UUID] = mapped_column(index=True) # filter index
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
deleted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))Services + Repos:
tenant_id (incl get_by_id)Migrations:
op.execute("CREATE TABLE IF NOT EXISTS ...")
op.execute("ALTER TABLE x ADD COLUMN IF NOT EXISTS ...")
op.execute("CREATE INDEX IF NOT EXISTS ...")NEVER op.create_table()/add_column()/create_index() (no idempotente).
NEVER sa.Enum(create_type=True) (broken SA 2.0.27).
Tests requeridos:
tests/modules/{m}/test_{name}_service.py — domain logic + happy/negative/edgetests/modules/{m}/test_{name}_endpoint.py — contract + tenant isolation + cross-tenant 403tests/modules/{m}/test_{name}_migration.py — idempotencyEventos emitidos / consumidos (si aplica):
shared/domain_events/outbox/Cross-cutting concerns:
.where(X.tenant_id == tenant_id)currency: str | NoneDateTime(timezone=True), store UTCSi tu propuesta toca core/config.py defaults flag side-effect:
→ Llenar sección § 9.5 Tests audit en 03-arch-be.md (flag, old/new default, side-effect path, tests grep, migration strategy, both values run).
Sin esto + flip → builder REVIEW FAIL automático.
Output al orchestrator:
done -> docs/projects/active/PI-N/sprints/SN/stories/{id}/03-arch-be.mdNO esperás más. Orchestrator reúne con otros 03-arch-* y produce 04-tickets.yaml.
response_model=tenant_id param (incl get_by_id)sa.Enum(create_type=True)'USD' defaultdatetime.utcnow() (use utc_now())Single artifact: 03-arch-be.md. Self-contained. Builder backend lee SOLO esto + handoff + spec.
d31f7bc
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.