Scaffold ArchiPy models under models/: domain/repository DTOs, errors, optional entities and types. Use for "add DTO/schema/request/response model", "new error type", or "SQLAlchemy entity".
Installs into .claude/skills of the current project.
Are you the author of Scaffold Models?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/syntaxarc-scaffold-models)
---
name: scaffold-models
description: >-
Scaffold ArchiPy models under models/: domain/repository DTOs, errors, optional
entities and types. Use for "add DTO/schema/request/response model", "new error type",
or "SQLAlchemy entity".
---
# Scaffold ArchiPy Models
## Scope
**Only** `models/`. Do not create repositories, logics, services, or helpers here.
## Read first
Read these plugin rules in full before generating files (paths relative to this skill directory; Claude Code: `${CLAUDE_SKILL_DIR}/../../rules/`):
- `../../rules/using-archipy-models.mdc`
- `../../rules/architecture-for-apps.mdc`
- `../../rules/using-archipy-utils.mdc`
## Before writing files
1. Inspect existing `models/` (DTOs, errors, entities, types), neighboring domains, and the installed ArchiPy version.
2. Infer domain name, DTO naming, and error grouping from existing modules.
3. Ask only for unresolved domain / operation names.
4. Preserve existing model modules; do not overwrite.
## Generate
```text
models/
├── dtos/<domain>/
│ ├── domain/v{n}/
│ │ ├── <op>_input_dto.py
│ │ └── <op>_output_dto.py
│ └── repository/
│ ├── <action>_command_dto.py
│ └── <action>_query_dto.py
├── errors/
│ └── <domain>_errors.py
├── entities/ # optional
│ └── <domain>_entity.py
└── types/ # optional
└── <domain>_types.py
```
Naming: `*InputDTO` / `*OutputDTO` for domain (versioned under `domain/v{n}/`); `*CommandDTO` / `*QueryDTO` /
`*ResponseDTO` for repository (never versioned). Any repository method with two or more parameters takes a single
`*CommandDTO` (write) / `*QueryDTO` (read) instead of positional arguments. Entities/DTOs for JWT-authenticated writes carry an explicit `actor_uuid` that fills `created_by*`/`updated_by*`
(actor from `current_actor`/`act` first, token `user_id`/`sub` second; never a path owner uuid).
Prefer ArchiPy `BaseDTO` and the exported `BaseError` hierarchy.
Verify imports against the app's installed ArchiPy version before writing.
Example shapes (`order` → rename):
```python
# models/dtos/order/domain/v1/order_create_input_dto.py
from pydantic import Field, PositiveInt
from archipy.models.dtos.base_dtos import BaseDTO
class OrderCreateInputDTO(BaseDTO):
"""Domain input crossing the service → logic boundary."""
customer_id: str = Field(min_length=1)
sku: str = Field(min_length=1)
quantity: PositiveInt
```
```python
# models/dtos/order/domain/v1/order_create_output_dto.py
from archipy.models.dtos.base_dtos import BaseDTO
class OrderCreateOutputDTO(BaseDTO):
"""Domain output returned to the service layer."""
order_id: str
status: str
```
```python
# models/dtos/order/repository/order_create_command_dto.py
from pydantic import PositiveInt
from archipy.models.dtos.base_dtos import BaseDTO
class OrderCreateCommandDTO(BaseDTO):
"""Repository write command — mapped from domain input inside the logic."""
customer_id: str
sku: str
quantity: PositiveInt
```
```python
# models/errors/order_errors.py
from archipy.models.errors import InvalidArgumentError, NotFoundError
class OrderNotFoundError(NotFoundError):
"""Raised when an order cannot be located."""
class OrderInvalidArgumentError(InvalidArgumentError):
"""Raised when order input fails domain validation."""
```
Prefer Pydantic's constrained types over `int = Field(gt=0)` / bare `str`: `PositiveInt`, `NonNegativeInt`,
`NonNegativeFloat`, `SecretStr` (tokens, passwords, API keys — never log or serialize the raw value), `HttpUrl`,
`EmailStr`, `UUID4`, `StringConstraints`, and the specific date/time types: `NaiveDatetime` (default for
timestamps; no timezone-aware fields), `PastDatetime`, `FutureDatetime`, `PastDate`, `FutureDate` — never bare `datetime` / `date`
when a stricter type fits. Reach for `pydantic-extra-types` (`PhoneNumber`,
`Country`, `Currency`, `Coordinate`, …) before hand-rolled validators; add it to the app's dependencies first. Read raw
secrets only at the boundary with `.get_secret_value()`. Reference: https://docs.pydantic.dev/latest/api/types/
Make DTOs reject invalid states at construction so downstream code and tests only see valid inputs: use
`@field_validator` for single-field rules and `@model_validator(mode="after")` for cross-field rules (ranges,
exactly-one-of, conditionally required fields). Prefer a type over a validator, and a discriminated union /
`Literal` / `StrEnum` over optional fields plus runtime `if`s. Validators are pure (no I/O; uniqueness and existence
checks stay in logics). Cover each validator with one invalid example at the DTO boundary.
For gRPC payloads extend `BaseProtobufDTO` instead of `BaseDTO` and set `_proto_class`. Unset proto3 scalars arrive
as `""` / `0`, so constrain them (`PositiveInt`, `StringConstraints(min_length=1)`); `to_proto` masks `SecretStr`, so
keep secrets out of response DTOs.
`BaseDTO` is frozen — do not mutate instances after validation. Prefer existing ArchiPy errors over near-duplicates.
Export public app errors from `models/errors/__init__.py` when other layers consume them. Prefer ArchiPy pagination /
sort / search DTOs before inventing page or cursor shapes.
## Do not
- Data structures only — no I/O, no business rules, no adapters, no DB sessions, no HTTP/gRPC types.
- Never import repositories, logics, or services from models.
- Do not version repository DTOs.
- Double quotes, Google-style docstrings, Python 3.14+ typing.
- No I/O, business rules, adapters, DB sessions, or HTTP/gRPC types in models.
- Do not mutate frozen `BaseDTO` instances after validation.
## Verify
1. Run the repository's formatter and linter on generated Python.
2. Confirm DTO naming, versioned domain vs unversioned repository layout, and error subclassing.
3. Import the new modules without constructing infrastructure.
4. Run the `archipy-reviewer` subagent on the changes and fix every **Must fix** finding it reports.
5. Report files and commands run.
## Docs
- https://syntaxarc.github.io/ArchiPy/getting-started/project_structure/
- https://syntaxarc.github.io/ArchiPy/tutorials/error_handling/
- Bundled: `../archipy-docs/reference.md` (DTO naming)