# Artworks Module – Canonical Architecture (SkinBase)

> **Authoritative documentation for Copilot AI agent**
> This file defines the **single source of truth** for the `artworks` domain.
> All generated code **MUST follow this document**.

---

## 1. Purpose

The **Artworks module** is the core content system of SkinBase.

It must support:

* high-read traffic (browse/search)
* safe moderation (soft deletes, approvals)
* multilingual content
* SEO-friendly URLs
* scalable statistics
* future extensions (tags, EXIF, search engines)

Legacy tables **must NOT influence new code**.

---

## 2. Core Design Principles (DO NOT VIOLATE)

1. **Single responsibility per table**
2. **No counters on hot tables**
3. **Soft deletes on user-generated content**
4. **No legacy fields**
5. **Slug-based routing only**
6. **FK integrity everywhere**
7. **Indexes optimized for browsing**
8. **Stats updated asynchronously**

---

## 3. Database Schema (Canonical)

### 3.1 `artworks` (CORE TABLE)

**Purpose:**
Stores the authoritative artwork entity.

```sql
artworks
```

**Fields:**

| Field        | Type         | Notes            |
| ------------ | ------------ | ---------------- |
| id           | bigint       | Primary key      |
| user_id      | bigint       | Owner            |
| title        | varchar(150) | Default language |
| slug         | varchar(160) | UNIQUE, URL      |
| description  | text         | Optional         |
| file_name    | varchar      | Original file    |
| file_path    | varchar      | Storage path     |
| file_size    | bigint       | Bytes            |
| mime_type    | varchar(64)  | e.g. image/jpeg  |
| width        | int          | Pixels           |
| height       | int          | Pixels           |
| is_public    | boolean      | Visibility       |
| is_approved  | boolean      | Moderation       |
| published_at | datetime     | SEO timing       |
| created_at   | datetime     |                  |
| updated_at   | datetime     |                  |
| deleted_at   | datetime     | Soft delete      |

**Indexes:**

* `UNIQUE(slug)`
* `(is_public, is_approved, published_at)`
* `deleted_at`

---

### 3.2 `artwork_translations`

**Purpose:**
Multilingual titles and descriptions.

```sql
artwork_translations
```

| Field       | Type     |
| ----------- | -------- |
| artwork_id  | FK       |
| locale      | char(2)  |
| title       | varchar  |
| description | text     |
| deleted_at  | datetime |

**Rules:**

* One row per `(artwork_id, locale)`
* Default language lives in `artworks`

---

### 3.3 `artwork_stats`

**Purpose:**
High-write counters isolated from core table.

```sql
artwork_stats
```

| Field        | Type    |
| ------------ | ------- |
| artwork_id   | PK + FK |
| views        | bigint  |
| downloads    | bigint  |
| favorites    | bigint  |
| rating_avg   | float   |
| rating_count | int     |

**Rules:**

* NO soft deletes
* Updated via jobs / async
* Never eager-loaded by default

---

### 3.4 `artwork_category`

**Purpose:**
Many-to-many relation with categories.

```sql
artwork_category
```

| Field       | Type |
| ----------- | ---- |
| artwork_id  | FK   |
| category_id | FK   |

**Rules:**

* Categories handle hierarchy
* Artworks can belong to multiple categories

---

### 3.5 `artwork_comments`

**Purpose:**
User comments with moderation.

```sql
artwork_comments
```

| Field       | Type     |
| ----------- | -------- |
| artwork_id  | FK       |
| user_id     | FK       |
| content     | text     |
| is_approved | boolean  |
| deleted_at  | datetime |

---

### 3.6 `artwork_downloads`

**Purpose:**
Audit log of downloads.

```sql
artwork_downloads
```

| Field      | Type       |
| ---------- | ---------- |
| artwork_id | FK         |
| user_id    | nullable   |
| ip         | binary(16) |
| user_agent | varchar    |
| created_at | datetime   |

**Rules:**

* Append-only
* No soft deletes
* Used for abuse detection & stats aggregation

---

## 4. Eloquent Models (REQUIRED)

### 4.1 Artwork Model

```php
App\Models\Artwork
```

**Traits:**

* `SoftDeletes`

**Relationships:**

```php
belongsTo(User::class)
hasMany(ArtworkTranslation::class)
hasOne(ArtworkStats::class)
belongsToMany(Category::class)
hasMany(ArtworkComment::class)
hasMany(ArtworkDownload::class)
```

**Required Scopes:**

```php
public function scopePublic($q)
public function scopeApproved($q)
public function scopePublished($q)
```

---

### 4.2 ArtworkTranslation

```php
App\Models\ArtworkTranslation
```

* SoftDeletes
* BelongsTo Artwork

---

### 4.3 ArtworkStats

```php
App\Models\ArtworkStats
```

* No SoftDeletes
* BelongsTo Artwork

---

### 4.4 ArtworkComment

```php
App\Models\ArtworkComment
```

* SoftDeletes
* BelongsTo Artwork
* BelongsTo User

---

### 4.5 ArtworkDownload

```php
App\Models\ArtworkDownload
```

* Append-only
* BelongsTo Artwork

---

## 5. Query Rules (IMPORTANT)

### Public browsing MUST always include:

```sql
WHERE
  deleted_at IS NULL
  AND is_public = 1
  AND is_approved = 1
```

### NEVER:

* eager-load stats on lists
* update counters inline
* expose IDs in URLs

---

## 6. Routing Rules

### Canonical URLs

```
/{content_type}/{category_path}/{artwork_slug}
```

Example:

```
/photography/abstract/dark/night-city
```

### Slug uniqueness is GLOBAL.

---

## 7. Search Rules

* Use MySQL FULLTEXT as fallback
* Prefer external search engines later
* Never search on `file_name` or paths

---

## 8. Caching Rules

* Category listings → Redis
* Homepage feeds → Redis
* Artwork stats → cached
* DB is source of truth

---

## 9. Soft Delete Behavior

| Action              | Result             |
| ------------------- | ------------------ |
| Soft delete artwork | Hidden from public |
| Restore             | Fully restored     |
| Force delete        | Rare, GDPR only    |

SEO:

* Soft-deleted artworks → 410 or 301

---

## 10. Forbidden Patterns (NEVER GENERATE)

❌ Counters on `artworks`
❌ IDs in URLs
❌ Hard deletes
❌ Category logic inside artworks
❌ Mixed language columns
❌ MyISAM
❌ Polymorphic abuse

---

## 11. Future Extensions (Allowed)

Copilot MAY extend with:

* `artwork_tags`
* `artwork_exif`
* `artwork_versions`
* `artwork_reports`
* external search engines

BUT must not modify core tables without migrations.

---

## 12. Final Rule (MANDATORY)

> **If generated code conflicts with this document,
> THIS DOCUMENT WINS.**
