current state

This commit is contained in:
2026-02-08 10:42:01 +01:00
parent 0a4372c40d
commit e055af9248
70 changed files with 4882 additions and 330 deletions

View File

@@ -0,0 +1,181 @@
# 1⃣ Final SQL New Favorites Table (Artwork-only)
**Table name:** `user_favorites`
**Scope:** users ↔ artworks
**Engine:** InnoDB
**Charset:** utf8mb4
```sql
CREATE TABLE user_favorites (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT UNSIGNED NOT NULL,
artwork_id BIGINT UNSIGNED NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uniq_user_artwork (user_id, artwork_id),
KEY idx_artwork (artwork_id),
KEY idx_user_created (user_id, created_at),
CONSTRAINT fk_user_favorites_user
FOREIGN KEY (user_id) REFERENCES users(id)
ON DELETE CASCADE,
CONSTRAINT fk_user_favorites_artwork
FOREIGN KEY (artwork_id) REFERENCES artworks(id)
ON DELETE CASCADE
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci;
```
This is **production-ready** and matches everything we discussed:
* no legacy fields
* no duplication
* proper constraints
* fast queries
---
# 2⃣ VS Code Agent Markdown (Laravel 12 Migration Prompt)
Save this as for example:
```
.vscode/agents/laravel-user-favorites-migration.md
```
or
```
.cursor/rules/laravel-user-favorites.md
```
---
```markdown
# Laravel 12 User Favorites Migration & Model
## Context
We are migrating legacy "favourites" functionality into a clean, modern Laravel 12 system.
Each user can add artworks to their favorites list.
This is a many-to-many relationship between users and artworks.
Legacy table MUST NOT be reused.
---
## Goal
Create a Laravel 12 database migration and Eloquent model for a new table named:
```
user_favorites
````
This table stores **which user favorited which artwork**, with a timestamp.
---
## Database Requirements
### Table: user_favorites
| Column | Type | Notes |
|------|------|------|
| id | BIGINT UNSIGNED | Primary key |
| user_id | BIGINT UNSIGNED | FK → users.id |
| artwork_id | BIGINT UNSIGNED | FK → artworks.id |
| created_at | TIMESTAMP | When artwork was favorited |
### Constraints & Indexes
- UNIQUE (user_id, artwork_id)
→ prevents duplicate favorites
- INDEX artwork_id
→ fast favorite count per artwork
- INDEX (user_id, created_at)
→ fast "my favorites" queries
### Foreign Keys
- user_id → users.id (ON DELETE CASCADE)
- artwork_id → artworks.id (ON DELETE CASCADE)
### Engine & Charset
- Engine: InnoDB
- Charset: utf8mb4
- Collation: utf8mb4_unicode_ci
---
## Laravel Migration Requirements
- Use `Schema::create`
- Use `foreignId()->constrained()->cascadeOnDelete()`
- Use `timestamps()` **ONLY if created_at is needed**
(do NOT add updated_at)
- Add explicit indexes and unique constraints
---
## Laravel Model Requirements
### Model: UserFavorite
- Table: `user_favorites`
- `$timestamps = false` (created_at handled manually or via DB default)
- Fillable:
- user_id
- artwork_id
- created_at
### Relationships
```php
UserFavorite belongsTo User
UserFavorite belongsTo Artwork
````
---
## Additional Notes
* This table is interaction-based, NOT content-based
* Do NOT store favorite counts here
* Favorite counts will be aggregated separately (Redis or statistics table)
* This table must be lean and write-optimized
---
## Deliverables
* Migration file for Laravel 12
* Eloquent model `UserFavorite`
* Proper naming and clean schema
* No legacy fields, no polymorphic logic
Generate clean, production-quality code.
````
---
## 3⃣ How to Use This in VS Code (Quick Steps)
1. Paste markdown into `.vscode/agents/` or `.cursor/rules/`
2. Open VS Code
3. Ask your AI agent:
> “Create Laravel 12 migration and model based on this document”
4. Review generated migration
5. Run:
```bash
php artisan migrate
````

View File

@@ -0,0 +1,312 @@
# Skinbase User Schema Review & Upgrade Plan
**Database:** MySQL / Percona 8.x
**Project:** Skinbase (new system, no legacy dependencies)
**Reviewed tables:** users, user_profiles, user_social_links, user_statistics
---
## 1. Overview
The current user-related database schema is **well designed**, modern, and suitable
for long-term growth.
Key strengths include:
- Clear separation of concerns
- Proper use of foreign keys and cascading deletes
- BigInt primary keys
- Soft deletes on users
- Migration-friendly legacy password handling
This document summarizes:
- what is already good
- recommended optimizations
- future-proofing steps (non-breaking)
- performance considerations for scale
---
## 2. users Table
### 2.1 Whats Good
- Unique `username` and `email`
- `legacy_password_algo` allows smooth migration from old systems
- `needs_password_reset` improves security posture
- Role stored as string allows flexibility in early stages
- Soft deletes enabled
### 2.2 Recommended Indexes
Add indexes for common query patterns:
```sql
CREATE INDEX idx_users_active ON users (is_active);
CREATE INDEX idx_users_role ON users (role);
CREATE INDEX idx_users_last_visit ON users (last_visit_at);
````
These improve:
* active user filtering
* admin queries
* “last seen” or online user features
### 2.3 Future Role Normalization (Planned)
Current approach is fine short-term:
```text
role = 'user' | 'admin' | 'moderator'
```
Planned future upgrade:
* `roles` table
* `user_roles` pivot table (many-to-many)
This allows:
* multiple roles per user
* temporary or scoped roles
* better permission modeling
⚠️ No immediate action required — just avoid hard-coding role logic.
### 2.4 Optional Security Enhancements
Recommended additions (optional but advised):
```sql
last_password_change_at TIMESTAMP NULL,
failed_login_attempts INT UNSIGNED DEFAULT 0,
locked_until TIMESTAMP NULL
```
Enables:
* rate limiting
* temporary account locking
* better auditability
---
## 3. user_profiles Table
### 3.1 Strengths
* Clean one-to-one relationship with `users`
* Public profile data separated from auth data
* Nullable fields for progressive profile completion
* Inclusive gender enum with safe default
* Localization-ready (`language`, `country_code`)
### 3.2 Country Handling Recommendation
Prefer using only:
```text
country_code (ISO 3166-1 alpha-2)
```
Benefits:
* language-independent
* avoids inconsistent country naming
* easier frontend mapping
`country` text field can be deprecated later if needed.
### 3.3 Avatar & Media Metadata (Future)
Current:
```text
avatar VARCHAR(255)
```
Recommended future approach:
```text
avatar_hash CHAR(64)
avatar_ext VARCHAR(10)
avatar_updated_at TIMESTAMP
```
This aligns with:
* hash-based file storage
* CDN-friendly URLs
* cache invalidation control
---
## 4. user_social_links Table
### 4.1 Current Design
* One row per platform per user
* Unique constraint on `(user_id, platform)`
* Cascade delete enabled
This is solid.
### 4.2 Platform Normalization (Recommended)
Current:
```text
platform VARCHAR(32)
```
Risk:
* inconsistent values (`twitter`, `x`, `Twitter`, etc.)
Options:
**Option A Enum (simple):**
```sql
ENUM('twitter','x','instagram','deviantart','artstation','github','website')
```
**Option B Reference Table (best long-term):**
* `social_platforms`
* foreign key `platform_id`
Option B is preferred for Skinbase as platforms evolve.
---
## 5. user_statistics Table
### 5.1 Strengths
* Isolated counters
* One row per user
* Minimal row size
* Clean FK relationship
### 5.2 Performance Warning (Important)
Avoid frequent direct updates like:
```sql
UPDATE user_statistics SET downloads = downloads + 1;
```
At scale, this causes:
* row locking
* write contention
* degraded performance
### 5.3 Recommended Strategy
* Use **Redis** (or in-memory cache) for real-time increments
* Periodically flush aggregated values to MySQL
* Use jobs / cron for batch updates
This ensures:
* fast user interactions
* scalable statistics tracking
---
## 6. Charset & Collation
Current:
```text
utf8mb4_unicode_ci
```
This is correct and safe.
Optional upgrade (MySQL 8+):
```text
utf8mb4_0900_ai_ci
```
Benefits:
* newer Unicode rules
* slightly better performance
Not required immediately.
---
## 7. Tables Planned for Future Expansion
Not required now, but expected as Skinbase grows:
### 7.1 user_activity_log
* logins
* uploads
* profile edits
* moderation actions
### 7.2 user_followers
* artist-to-artist following
* social graph features
### 7.3 user_settings
* privacy preferences
* notification settings
* email subscriptions
These should remain **separate tables** to avoid bloating `users`.
---
## 8. Laravel Implementation Notes
Recommended model casting:
```php
protected $casts = [
'is_active' => 'boolean',
'needs_password_reset' => 'boolean',
'email_verified_at' => 'datetime',
'last_visit_at' => 'datetime',
];
```
Best practices:
* Eager load profiles (`with('profile')`)
* Cache public profile + statistics
* Keep statistics out of main user queries
---
## 9. Final Verdict
**Schema quality:** Excellent
**Scalability:** Very good
**Migration readiness:** Excellent
**Long-term Skinbase fit:** Excellent
The current schema is production-ready and significantly better than typical legacy
user databases. Most future improvements can be introduced **without breaking changes**.
Primary future wins:
* Redis-backed statistics
* normalized roles and social platforms
* hash-based media storage
---
**Status:** Approved for production
**Next steps:** API design, public profile queries, legacy user migration
```