- Note that plan limits ARE enforced in most create endpoints - Add specific task for BulkCreateLinksEndpoint plan limits check Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
428 lines
14 KiB
Markdown
428 lines
14 KiB
Markdown
# TrakQR Implementation Tasks
|
|
|
|
> This file tracks implementation progress. Update status as work completes.
|
|
|
|
## Status Legend
|
|
- [ ] Not started
|
|
- [~] In progress / Partial
|
|
- [x] Complete
|
|
|
|
---
|
|
|
|
## Phase 1: Foundation (Complete)
|
|
|
|
### Database & Models
|
|
- [x] PostgreSQL setup
|
|
- [x] EF Core configuration
|
|
- [x] User entity
|
|
- [x] Workspace entity
|
|
- [x] Project entity
|
|
- [x] ShortLink entity
|
|
- [x] QRCodeDesign entity
|
|
- [x] Domain entity
|
|
- [x] Event entity
|
|
- [x] Asset entity
|
|
- [x] ApiKey entity
|
|
- [x] EmailVerificationToken entity
|
|
- [x] PasswordResetToken entity
|
|
|
|
### Authentication
|
|
- [x] User registration endpoint (`POST /auth/register`)
|
|
- [x] User login endpoint (`POST /auth/login`)
|
|
- [x] JWT token generation
|
|
- [x] Forgot password endpoint (`POST /auth/forgot`)
|
|
- [x] Reset password endpoint (`POST /auth/reset`)
|
|
- [x] Email verification endpoint (`POST /auth/verify-email`)
|
|
- [x] Resend verification endpoint (`POST /auth/resend-verification`)
|
|
- [x] Get profile endpoint (`GET /auth/profile`)
|
|
- [x] Update profile endpoint (`PUT /auth/profile`)
|
|
- [x] Change password endpoint (`POST /auth/change-password`)
|
|
- [x] Delete account endpoint (`DELETE /auth/account`)
|
|
|
|
### Workspaces & Projects
|
|
- [x] Create workspace (`POST /workspaces`)
|
|
- [x] List workspaces (`GET /workspaces`)
|
|
- [x] Get workspace (`GET /workspaces/{id}`)
|
|
- [x] Update workspace (`PUT /workspaces/{id}`)
|
|
- [x] Delete workspace (`DELETE /workspaces/{id}`)
|
|
- [x] Create project (`POST /workspaces/{id}/projects`)
|
|
- [x] List projects (`GET /workspaces/{id}/projects`)
|
|
- [x] Get project (`GET /workspaces/{id}/projects/{id}`)
|
|
- [x] Update project (`PUT /workspaces/{id}/projects/{id}`)
|
|
- [x] Delete project (`DELETE /workspaces/{id}/projects/{id}`)
|
|
- [x] Auto-create default workspace on signup
|
|
- [x] Ownership verification / access control
|
|
|
|
### Testing Infrastructure
|
|
- [x] ApiWebApplicationFactory for integration tests
|
|
- [x] Project endpoint tests
|
|
- [x] Workspace endpoint tests
|
|
- [x] Link endpoint tests
|
|
- [x] Auth endpoint tests
|
|
- [x] Domain endpoint tests
|
|
|
|
---
|
|
|
|
## Phase 2: Core Link Features (Complete)
|
|
|
|
### Short Link CRUD
|
|
- [x] Create short link endpoint (`POST /workspaces/{id}/links`)
|
|
- Custom slug or auto-generate
|
|
- URL validation
|
|
- Title (optional)
|
|
- Project assignment (optional)
|
|
- Domain selection
|
|
- [x] List short links (`GET /workspaces/{id}/links`)
|
|
- Filter by project
|
|
- Filter by status
|
|
- Include deleted (soft delete support)
|
|
- [x] Get short link (`GET /workspaces/{id}/links/{id}`)
|
|
- [x] Update short link (`PUT /workspaces/{id}/links/{id}`)
|
|
- [x] Delete short link (`DELETE /workspaces/{id}/links/{id}`) - soft delete
|
|
- [x] Restore short link (`POST /workspaces/{id}/links/{id}/restore`)
|
|
- [x] Bulk create links (`POST /workspaces/{id}/links/bulk`)
|
|
|
|
### Public Redirect Endpoint
|
|
- [x] `GET /{slug}` redirect endpoint
|
|
- Resolve domain + slug to destination
|
|
- Check link exists
|
|
- Check link is active
|
|
- Check not expired
|
|
- Check password (if protected)
|
|
- Log event (async, non-blocking)
|
|
- Return 302 redirect
|
|
- [x] Password-protected link handling (`POST /{slug}`)
|
|
- [x] Rate limiting on redirect endpoint
|
|
|
|
---
|
|
|
|
## Phase 3: Event Tracking & Analytics (Complete)
|
|
|
|
### Event Logging
|
|
- [x] Event logging service (`IEventTrackingService`)
|
|
- IP hashing (privacy)
|
|
- User agent parsing (device type)
|
|
- GeoIP lookup (country) - MaxMind GeoIP2 integrated
|
|
- Referrer capture
|
|
- Dedupe key generation (30-min window)
|
|
- [x] Click event recording (from redirect)
|
|
- [x] Scan event recording (from QR with `?qr=` param)
|
|
- [x] Async/background event processing
|
|
|
|
### Analytics Endpoints
|
|
- [x] Workspace analytics (`GET /workspaces/{id}/analytics`)
|
|
- Total clicks/scans
|
|
- Unique visitors
|
|
- Time series data
|
|
- Top links breakdown
|
|
- Device breakdown
|
|
- Referrer breakdown
|
|
- Country breakdown (geo)
|
|
- [x] Link analytics (`GET /workspaces/{id}/links/{id}/analytics`)
|
|
- [x] QR code analytics (`GET /workspaces/{id}/qrcodes/{id}/analytics`)
|
|
- [x] Time filters (24h, 7d, 30d)
|
|
- [~] Custom date range filter (backend supports startDate/endDate, frontend needs UI)
|
|
|
|
---
|
|
|
|
## Phase 4: QR Code Designer (Complete)
|
|
|
|
### QR Code Generation
|
|
- [x] QR code generation service (`IQRCodeGeneratorService`)
|
|
- QRCoder library
|
|
- Error correction levels (L/M/Q/H)
|
|
- Quiet zone configuration
|
|
- PNG and SVG output
|
|
- [x] QR code design model integration
|
|
- Foreground/background colors
|
|
- Module shapes (Square, Rounded, Dots)
|
|
- Eye shapes (Square, Rounded, Circle)
|
|
- Logo embedding with size control
|
|
|
|
### QR Code Endpoints
|
|
- [x] Create QR design (`POST /workspaces/{id}/qrcodes`)
|
|
- [x] List QR designs (`GET /workspaces/{id}/qrcodes`)
|
|
- [x] Get QR design (`GET /workspaces/{id}/qrcodes/{id}`)
|
|
- [x] Update QR design (`PUT /workspaces/{id}/qrcodes/{id}`)
|
|
- [x] Delete QR design (`DELETE /workspaces/{id}/qrcodes/{id}`)
|
|
- [x] Preview QR (`GET /workspaces/{id}/qrcodes/{id}/preview`)
|
|
- [x] Export QR (`GET /workspaces/{id}/qrcodes/{id}/export?format=png|svg&size=N`)
|
|
- [x] QR exports include `?qr={id}` for scan attribution
|
|
|
|
### Asset Management
|
|
- [x] Upload asset endpoint (`POST /workspaces/{id}/assets`)
|
|
- [x] List assets (`GET /workspaces/{id}/assets`)
|
|
- [x] Get asset (`GET /assets/{storageKey}`)
|
|
- [x] Delete asset (`DELETE /workspaces/{id}/assets/{id}`)
|
|
|
|
---
|
|
|
|
## Phase 5: Domain Management (Complete)
|
|
|
|
### Custom Domains
|
|
- [x] Add domain (`POST /workspaces/{id}/domains`)
|
|
- [x] List domains (`GET /workspaces/{id}/domains`)
|
|
- [x] Get domain (`GET /workspaces/{id}/domains/{id}`)
|
|
- [x] Delete domain (`DELETE /workspaces/{id}/domains/{id}`)
|
|
- [x] Verify domain (`POST /workspaces/{id}/domains/{id}/verify`)
|
|
- Generate verification token
|
|
- DNS TXT record verification
|
|
- Mark as verified
|
|
|
|
---
|
|
|
|
## Phase 6: Frontend Dashboard (Complete)
|
|
|
|
### Authentication UI
|
|
- [x] Login page
|
|
- [x] Registration page
|
|
- [x] Forgot password page
|
|
- [x] Password reset page
|
|
- [x] Email verification page
|
|
- [x] Auth state management (Pinia store)
|
|
|
|
### Dashboard
|
|
- [x] Workspace switcher with create/manage modals
|
|
- [x] Dashboard home (overview stats, charts, breakdowns)
|
|
- [x] Navigation/sidebar (AppLayout component)
|
|
|
|
### Link Management UI
|
|
- [x] Links list view with trash/restore
|
|
- [x] Create link modal with UTM builder
|
|
- [x] Edit link modal
|
|
- [x] Link details with analytics
|
|
- [x] Bulk import modal
|
|
|
|
### QR Designer UI
|
|
- [x] QR codes list with preview thumbnails
|
|
- [x] QR designer page with color pickers
|
|
- [x] Shape selectors (modules and eyes)
|
|
- [x] Logo upload integration
|
|
- [x] Live preview
|
|
- [x] Export buttons (PNG/SVG)
|
|
- [x] Style presets (6 presets)
|
|
- [x] QR code detail/analytics page
|
|
|
|
### Other UI Pages
|
|
- [x] Analytics page with time series, breakdowns, geo
|
|
- [x] Projects page with CRUD
|
|
- [x] Domains page with verification flow
|
|
- [x] Settings page (profile, password, API keys, delete account)
|
|
- [x] Billing page with plan display and upgrade flow
|
|
|
|
### State Management
|
|
- [x] Pinia stores (auth, workspace)
|
|
- [x] localStorage persistence for workspace selection
|
|
- [x] Automatic data refresh on workspace change
|
|
- [x] Proper initialization flow in App.vue
|
|
|
|
---
|
|
|
|
## Phase 7: Production Readiness (Complete)
|
|
|
|
### Security & Performance
|
|
- [x] Rate limiting (auth and redirect endpoints)
|
|
- [x] CORS configuration
|
|
- [x] Global exception handling middleware
|
|
- [x] Request error logging
|
|
|
|
### Email System
|
|
- [x] Email service interface (`IEmailService`)
|
|
- [x] Console email service (development)
|
|
- [x] SMTP email service (production)
|
|
- [x] Email templates (verification, password reset)
|
|
- [x] Email verification flow
|
|
- [x] Password reset emails
|
|
|
|
### Plan & Quotas
|
|
- [x] Usage tracking service (`IPlanLimitsService`)
|
|
- [x] Plan limits configuration (Free, Pro, Business)
|
|
- [x] Usage endpoint (`GET /usage`)
|
|
- [~] Plan limits enforcement in create endpoints (service exists, needs integration)
|
|
|
|
### API Keys
|
|
- [x] Create API key (`POST /workspaces/{id}/api-keys`)
|
|
- [x] List API keys (`GET /workspaces/{id}/api-keys`)
|
|
- [x] Delete API key (`DELETE /workspaces/{id}/api-keys/{id}`)
|
|
- [ ] API key authentication middleware
|
|
|
|
---
|
|
|
|
## Phase 8: Payments & Billing (Complete)
|
|
|
|
### Stripe Integration
|
|
- [x] Stripe service (`IStripeService`)
|
|
- [x] Stripe settings configuration
|
|
- [x] Checkout session endpoint (`POST /billing/checkout`)
|
|
- [x] Customer portal endpoint (`POST /billing/portal`)
|
|
- [x] Subscription endpoint (`GET /workspaces/{id}/subscription`)
|
|
- [x] Webhook handling (`POST /billing/webhook`)
|
|
- [x] Billing UI with plan comparison
|
|
|
|
---
|
|
|
|
## Remaining Tasks
|
|
|
|
### High Priority
|
|
|
|
1. **API Key Authentication**
|
|
- [ ] Middleware to authenticate requests using API keys
|
|
- [ ] Scope validation (read, write, admin)
|
|
|
|
2. **Plan Limits in Bulk Operations**
|
|
- [ ] Add plan limits check in `BulkCreateLinksEndpoint`
|
|
- Plan limits already enforced in: CreateLink, CreateQRCode, CreateWorkspace, AddDomain
|
|
|
|
3. **Custom Date Range UI**
|
|
- [ ] Add date picker to analytics pages
|
|
- [ ] Backend already supports `startDate`/`endDate` params
|
|
|
|
### Medium Priority
|
|
|
|
4. **Background Jobs**
|
|
- [ ] Periodic domain verification checks
|
|
- [ ] Event retention cleanup (delete old events per plan)
|
|
- [ ] Monthly IP salt rotation for privacy
|
|
|
|
5. **Input Validation**
|
|
- [ ] URL allowlist/denylist for abuse prevention
|
|
- [ ] Stricter input sanitization
|
|
|
|
6. **Testing**
|
|
- [ ] Add tests for new auth endpoints
|
|
- [ ] Add tests for billing endpoints
|
|
- [ ] Add tests for API key endpoints
|
|
|
|
### Lower Priority
|
|
|
|
7. **Print-Ready QR Options**
|
|
- [ ] High contrast mode toggle
|
|
- [ ] CMYK color support
|
|
|
|
8. **Advanced Analytics**
|
|
- [ ] Export analytics data (CSV/JSON)
|
|
- [ ] Scheduled reports
|
|
|
|
9. **Webhooks**
|
|
- [ ] User-configurable webhooks for click events
|
|
|
|
---
|
|
|
|
## Architecture Notes
|
|
|
|
- **Backend**: ASP.NET Core with FastEndpoints (vertical slice architecture)
|
|
- **Frontend**: Vue 3 + Vite + Pinia + Vue Router
|
|
- **Database**: PostgreSQL with EF Core
|
|
- **Features**: Located in `src/api/Features/{Feature}/`
|
|
- **Authentication**: JWT tokens, rate-limited auth endpoints
|
|
- **Email**: Pluggable service (Console for dev, SMTP for prod)
|
|
- **Payments**: Stripe integration with webhooks
|
|
|
|
---
|
|
|
|
## API Endpoints Summary
|
|
|
|
### Auth
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| POST | /auth/register | Register new user |
|
|
| POST | /auth/login | Login |
|
|
| POST | /auth/forgot | Request password reset |
|
|
| POST | /auth/reset | Reset password with token |
|
|
| POST | /auth/verify-email | Verify email with token |
|
|
| POST | /auth/resend-verification | Resend verification email |
|
|
| GET | /auth/profile | Get current user profile |
|
|
| PUT | /auth/profile | Update profile |
|
|
| POST | /auth/change-password | Change password |
|
|
| DELETE | /auth/account | Delete account |
|
|
|
|
### Workspaces
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | /workspaces | List user's workspaces |
|
|
| POST | /workspaces | Create workspace |
|
|
| GET | /workspaces/{id} | Get workspace |
|
|
| PUT | /workspaces/{id} | Update workspace |
|
|
| DELETE | /workspaces/{id} | Delete workspace |
|
|
|
|
### Projects
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | /workspaces/{id}/projects | List projects |
|
|
| POST | /workspaces/{id}/projects | Create project |
|
|
| GET | /workspaces/{id}/projects/{pid} | Get project |
|
|
| PUT | /workspaces/{id}/projects/{pid} | Update project |
|
|
| DELETE | /workspaces/{id}/projects/{pid} | Delete project |
|
|
|
|
### Links
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | /workspaces/{id}/links | List links |
|
|
| POST | /workspaces/{id}/links | Create link |
|
|
| POST | /workspaces/{id}/links/bulk | Bulk create links |
|
|
| GET | /workspaces/{id}/links/{lid} | Get link |
|
|
| PUT | /workspaces/{id}/links/{lid} | Update link |
|
|
| DELETE | /workspaces/{id}/links/{lid} | Soft delete link |
|
|
| POST | /workspaces/{id}/links/{lid}/restore | Restore deleted link |
|
|
| GET | /workspaces/{id}/links/{lid}/analytics | Get link analytics |
|
|
|
|
### QR Codes
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | /workspaces/{id}/qrcodes | List QR codes |
|
|
| POST | /workspaces/{id}/qrcodes | Create QR code |
|
|
| GET | /workspaces/{id}/qrcodes/{qid} | Get QR code |
|
|
| PUT | /workspaces/{id}/qrcodes/{qid} | Update QR code |
|
|
| DELETE | /workspaces/{id}/qrcodes/{qid} | Delete QR code |
|
|
| GET | /workspaces/{id}/qrcodes/{qid}/preview | Get QR preview (data URL) |
|
|
| GET | /workspaces/{id}/qrcodes/{qid}/export | Export QR (PNG/SVG) |
|
|
| GET | /workspaces/{id}/qrcodes/{qid}/analytics | Get QR analytics |
|
|
|
|
### Domains
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | /workspaces/{id}/domains | List domains |
|
|
| POST | /workspaces/{id}/domains | Add domain |
|
|
| GET | /workspaces/{id}/domains/{did} | Get domain |
|
|
| DELETE | /workspaces/{id}/domains/{did} | Delete domain |
|
|
| POST | /workspaces/{id}/domains/{did}/verify | Verify domain |
|
|
|
|
### Assets
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | /workspaces/{id}/assets | List assets |
|
|
| POST | /workspaces/{id}/assets | Upload asset |
|
|
| DELETE | /workspaces/{id}/assets/{aid} | Delete asset |
|
|
| GET | /assets/{storageKey} | Get asset file (public) |
|
|
|
|
### Analytics
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | /workspaces/{id}/analytics | Workspace analytics |
|
|
|
|
### API Keys
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | /workspaces/{id}/api-keys | List API keys |
|
|
| POST | /workspaces/{id}/api-keys | Create API key |
|
|
| DELETE | /workspaces/{id}/api-keys/{kid} | Delete API key |
|
|
|
|
### Billing
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| POST | /billing/checkout | Create Stripe checkout session |
|
|
| POST | /billing/portal | Create Stripe portal session |
|
|
| GET | /workspaces/{id}/subscription | Get subscription details |
|
|
| POST | /billing/webhook | Stripe webhook handler |
|
|
|
|
### Usage
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | /usage | Get usage stats and limits |
|
|
|
|
### Public
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | /{slug} | Redirect to destination |
|
|
| POST | /{slug} | Redirect with password |
|