### ENTITY_NAME
One sentence describing the entity.
| Attribute | Description | Data Type | Length/Precision | Validation Rules |
|-----------|-------------|-----------|------------------|-----------------------|
| id | ... | Long | 19 | Primary Key, Sequence |
| ... | ... | ... | ... | ... |
## Required Format for Each Entity
Every entity MUST have:
1. A ### heading with the entity name in UPPERCASE (UPPER_SNAKE_CASE, e.g. `### ROOM_TYPE` — never `### Room Type` or `## Entity: Room Type`)
2. One sentence description
3. An attribute table with exactly these 5 columns in this order: Attribute, Description, Data Type, Length/Precision, Validation Rules
### Example Entity
### ROOM_TYPE
Defines categories of rooms with shared characteristics.
| Attribute | Description | Data Type | Length/Precision | Validation Rules |
|-------------|--------------------------|-----------|------------------|---------------------------|
| id | Unique identifier | Long | 19 | Primary Key, Sequence |
| name | Name of the room type | String | 50 | Not Null, Unique |
| description | Detailed description | String | 500 | Optional |
| capacity | Maximum number of guests | Integer | 10 | Not Null, Min: 1, Max: 10 |
| price | Price per night in CHF | Decimal | 10,2 | Not Null, Min: 0 |
## Mermaid Diagram Rules
- Show entity names and relationships ONLY
- NO attributes inside entity blocks
- Use relationship syntax: `ENTITY_A ||--o{ ENTITY_B : "relationship"`
## Data Types (use only these)
The Data Type column must use exactly these values — never SQL or ORM types such as
VARCHAR, TEXT, CHAR, bigint, numeric, serial, smallint, UUID, Timestamp, or Enum:
| Data Type | Length/Precision | Usage |
|-----------|------------------|-----------------------|
| Long | 19 | IDs, foreign keys |
| String | varies (50-500) | Text fields |
| Integer | 10 | Whole numbers |
| Decimal | 10,2 | Currency, percentages |
| Boolean | 1 | True/false flags |
| Date | - | Date only |
| DateTime | - | Date and time |
The Length/Precision column holds the bare value (e.g. `10,2`) — never a type
expression like `DECIMAL(10,2)`.
The seven types are the complete list. Binary content (a document, an image) has no type of its own: it is a
`String` with `-` as Length/Precision and a Description that begins with `Binary content:` (`Binary content: the
signed contract as PDF`); its Validation Rules are `Not Null` or `Optional` as for any field. The migration
skill of every stack maps exactly that combination to a binary column, and the persistence code follows the column.
## Validation Rules (use only these values)
Compose every Validation Rules cell from this vocabulary, using the exact wording —
never a prose description, and never an empty cell, dash, or "N/A":
**Keys** — a key column takes exactly one of these values:
| Attribute Type | Validation Rules Value |
|-------------------------------|-------------------------------------|
| Primary key | Primary Key, Sequence |
| Natural or composite key | Primary Key |
| Composite key and foreign key | Primary Key, Foreign Key (TABLE.id) |
**Every other attribute** — one nullability rule first, then any of the following rules that apply, in this order:
| Position | Rule | Meaning |
|----------|--------------------------|----------------------------------------------------------------------------|
| 1 | `Not Null` or `Optional` | Required or optional; always present, always first |
| 2 | `Unique` | No two rows share the value (an optional value: no two non-empty ones) |
| 3 | `Foreign Key (TABLE.id)` | References another entity, or an external entity named under the title |
| 4 | `Min: X, Max: Y` | Range of a number, or of a date as ISO dates; always both bounds |
| 4 | `Values: A, B, C` | A fixed set of values; instead of a range, never together with one |
| 5 | `Format: <format>` | The value follows a format: `Email`, `Phone` (international, E.164), `URL` |
| Attribute Type | Validation Rules Value |
|-------------------------------|---------------------------------------------|
| Required field | Not Null |
| Optional field | Optional |
| Unique field | Not Null, Unique |
| Foreign key | Not Null, Foreign Key (TABLE.id) |
| One-to-one link | Not Null, Unique, Foreign Key (TABLE.id) |
| With range | Not Null, Min: X, Max: Y |
| With values | Not Null, Values: A, B, C |
| Email | Not Null, Format: Email |
| Unique email | Not Null, Unique, Format: Email |
| Optional phone number | Optional, Format: Phone |
Examples: an email attribute is `Not Null, Format: Email` — never "must be a valid
email address"; an email address no two members share is `Not Null, Unique, Format: Email`. A status attribute with a fixed set of states is
`Not Null, Values: Pending, Active, Completed, Cancelled` — never "must be one of
Pending, Active, Completed, Cancelled".
The vocabulary is **closed**: a cell holds only the rules above, in the order of the Position column, each
at most once, and nothing else — no prose, no rule of your own (`Format: Swiss postal code` is invalid; a format
the list lacks is a `#### Constraints` bullet). Never write `Min:` without its matching `Max:` (`Not Null, Min: 0`
alone is invalid — use `Not Null, Min: 0, Max: <upper bound>` or just `Not Null`), and never combine `Values:` with
a range.
The same tables are available in [references/REFERENCE.md](references/REFERENCE.md). The path is relative to the folder containing this SKILL.md, not to the project root.
## Multi-Column Constraints
If validation spans multiple columns, add a `#### Constraints` heading below the entity's
attribute table and list each constraint as a bullet, one rule per bullet: