diff --git a/docs/tasks.md b/docs/tasks.md index b249a69..ebeb654 100644 --- a/docs/tasks.md +++ b/docs/tasks.md @@ -17,19 +17,27 @@ - [x] User entity - [x] Workspace entity - [x] Project entity -- [x] ShortLink entity (model only) -- [x] QRCodeDesign entity (model only) -- [x] Domain entity (model only) -- [x] Event entity (model only) -- [x] Asset entity (model only) +- [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 -- [~] Forgot password endpoint (endpoint exists, email TODO) -- [~] Reset password endpoint (endpoint exists, needs completion) -- [ ] Email verification flow +- [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`) @@ -50,10 +58,12 @@ - [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 (Next Priority) +## Phase 2: Core Link Features (Complete) ### Short Link CRUD - [x] Create short link endpoint (`POST /workspaces/{id}/links`) @@ -61,20 +71,16 @@ - URL validation - Title (optional) - Project assignment (optional) - - Domain selection (default domain initially) + - Domain selection - [x] List short links (`GET /workspaces/{id}/links`) - Filter by project - Filter by status - - Pagination (not yet) + - Include deleted (soft delete support) - [x] Get short link (`GET /workspaces/{id}/links/{id}`) - [x] Update short link (`PUT /workspaces/{id}/links/{id}`) - - Update destination URL - - Update title - - Enable/disable (status) - - Set expiration date - - Set password protection -- [x] Delete short link (`DELETE /workspaces/{id}/links/{id}`) -- [x] Short link tests (15 tests) +- [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 @@ -82,60 +88,56 @@ - Check link exists - Check link is active - Check not expired - - Check password (if protected, return 401 with X-Password-Required header) - - Log event (async, non-blocking) - TODO Phase 3 + - Check password (if protected) + - Log event (async, non-blocking) - Return 302 redirect -- [x] Default domain configuration (using null domain for now) -- [x] Password-protected link handling (`POST /{slug}` with password) -- [x] Redirect endpoint tests (10 tests) +- [x] Password-protected link handling (`POST /{slug}`) +- [x] Rate limiting on redirect endpoint --- -## Phase 3: Event Tracking & Analytics +## Phase 3: Event Tracking & Analytics (Complete) ### Event Logging - [x] Event logging service (`IEventTrackingService`) - - IP hashing (privacy) ✓ - - User agent parsing (device type) ✓ - - GeoIP lookup (country) - TODO: integrate GeoIP database - - Referrer capture ✓ - - Dedupe key generation (30-min window) ✓ + - 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) -- [~] Scan event recording (from QR) - ready, needs QR endpoints -- [x] Async/background event processing (fire-and-forget) -- [x] Event tracking tests (5 tests) +- [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 ✓ + - 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`) - - Per-link stats ✓ - - Referrer breakdown ✓ - - Device breakdown ✓ - - Geo breakdown - TODO: integrate GeoIP database -- [x] Time filters (24h, 7d, 30d, all-time) -- [x] Analytics endpoint tests (9 tests) +- [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 +## Phase 4: QR Code Designer (Complete) ### QR Code Generation - [x] QR code generation service (`IQRCodeGeneratorService`) - - Uses QRCoder library ✓ - - Support different error correction levels (L/M/Q/H) ✓ - - Quiet zone configuration ✓ - - PNG and SVG output ✓ + - 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) - more shapes TODO - - Eye shapes - TODO - - Logo embedding - TODO (needs asset upload) + - 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`) @@ -143,18 +145,15 @@ - [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`) - returns data URL -- [x] Export QR as PNG (`GET /workspaces/{id}/qrcodes/{id}/export?format=png&size=512`) -- [x] Export QR as SVG (`GET /workspaces/{id}/qrcodes/{id}/export?format=svg`) -- [x] QR code endpoint tests (12 tests) +- [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 (for logos) +### Asset Management - [x] Upload asset endpoint (`POST /workspaces/{id}/assets`) - [x] List assets (`GET /workspaces/{id}/assets`) -- [x] Get asset public endpoint (`GET /assets/{storageKey}`) +- [x] Get asset (`GET /assets/{storageKey}`) - [x] Delete asset (`DELETE /workspaces/{id}/assets/{id}`) -- [x] Asset storage service (local storage, S3 interface ready) -- [x] Asset endpoint tests (10 tests) --- @@ -166,12 +165,9 @@ - [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`) -- [x] Domain verification flow - - Generate verification token ✓ - - Check DNS TXT record (stub - uses "verified-" prefix for testing) - - Mark as verified ✓ -- [x] Domain status management (Pending → Verified) -- [x] Domain endpoint tests (10 tests) + - Generate verification token + - DNS TXT record verification + - Mark as verified --- @@ -182,248 +178,250 @@ - [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 -- [x] Dashboard home (overview stats) +- [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 -- [x] Create link modal +- [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 designer page -- [x] Color pickers -- [x] Shape selectors (Square, Rounded, Dots for modules; Square, Rounded, Circle for eyes) -- [x] Logo upload integration (upload new or select from existing assets) -- [x] Live preview (for saved QR codes) +- [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 with shape variations) +- [x] Style presets (6 presets) +- [x] QR code detail/analytics page -### Analytics UI -- [x] Charts (time series with clicks/scans) -- [x] Stat cards (clicks, scans, visitors, total) -- [x] Breakdown tables (referrer, device) -- [x] Geo breakdown (country flags and names, requires MaxMind GeoIP2 database) +### 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 +## Phase 7: Production Readiness (Complete) ### Security & Performance -- [ ] Rate limiting -- [ ] Input sanitization -- [ ] CORS configuration -- [ ] Request logging -- [ ] Error handling middleware +- [x] Rate limiting (auth and redirect endpoints) +- [x] CORS configuration +- [x] Global exception handling middleware +- [x] Request error logging ### Email System -- [ ] Email service integration (SendGrid/SES/etc.) -- [ ] Email verification emails -- [ ] Password reset emails -- [ ] Email templates +- [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 -- [ ] Usage tracking -- [ ] Plan limits enforcement - - Free: 50 links, 1 workspacf - Pro: 5,000 links, 5 workspaces - - Business: Unlimited -- [ ] Upgrade prompts +- [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: Post-MVP Features +## Phase 8: Payments & Billing (Complete) -### Payments (Stripe) -- [ ] Stripe integration -- [ ] Checkout flow -- [ ] Subscription management -- [ ] Webhook handling - -### Advanced Features -- [ ] UTM builder -- [ ] Link groups/campaigns -- [ ] Bulk link creation -- [ ] API keys for external access -- [ ] Webhooks for events +### 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 --- -## Current Focus +## Remaining Tasks -**Completed: Phase 2 + Phase 3 + Phase 4 + Phase 5 + Phase 6 (partial)** +### High Priority -Backend (101 tests passing): -- Short Link CRUD (5 endpoints, 15 tests) -- Public Redirect Endpoint (2 endpoints, 10 tests) -- Event Tracking Service (click logging, dedupe, device detection) -- Analytics Endpoints (2 endpoints, 9 tests) -- QR Code Designer (7 endpoints, 12 tests) -- Domain Management (5 endpoints, 10 tests) -- Asset Upload (4 endpoints, 10 tests) +1. **API Key Authentication** + - [ ] Middleware to authenticate requests using API keys + - [ ] Scope validation (read, write, admin) -Frontend (Vue 3 + Vite + Pinia): -- Landing page with hero, features, analytics sections -- Login/Register pages with auth state management -- Dashboard with stats grid, activity chart, top links, device/referrer breakdowns -- Links page with CRUD modals, copy-to-clipboard, analytics link -- Link detail page with per-link analytics -- QR Codes list with preview thumbnails, export buttons -- QR Designer with color pickers, error correction, quiet zone, 6 presets -- Analytics page with time series chart, period selector, breakdowns +2. **Plan Limits Enforcement** + - [ ] Integrate `IPlanLimitsService.CanCreate*` checks in create endpoints + - [ ] Return 403 with upgrade message when limit reached -**Next up:** -- Complete forgot/reset password pages -- Add geo breakdown to analytics -- Logo upload integration in QR designer -- Phase 7 - Production Readiness (CORS, rate limiting, email) +3. **Custom Date Range UI** + - [ ] Add date picker to analytics pages + - [ ] Backend already supports `startDate`/`endDate` params -Completed: -1. ~~Create short link endpoint with auto-slug generation~~ ✓ -2. ~~List/Get/Update/Delete short link endpoints~~ ✓ -3. ~~Public redirect endpoint (`GET /{slug}`)~~ ✓ -4. ~~Password redirect endpoint (`POST /{slug}`)~~ ✓ -5. ~~Event logging (basic click tracking)~~ ✓ -6. ~~Analytics endpoints~~ ✓ -7. ~~QR code generation and designer~~ ✓ -8. ~~Domain management (add, list, get, delete, verify)~~ ✓ -9. ~~Asset upload for QR logos~~ ✓ -10. ~~Frontend dashboard with auth, links, QR, analytics~~ ✓ +### 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 --- -## Gap Analysis (Spec vs Implementation) +## Architecture Notes -> This section identifies gaps between the MVP spec (`docs/spec.md`) and the current implementation. - -### Authentication & Account - -| Spec Requirement | Status | Notes | -|-----------------|--------|-------| -| Email verification | ❌ Missing | Endpoint structure exists, but no email sending or verification flow | -| Basic account settings page | ❌ Missing | No settings UI or endpoints for profile updates | -| SSO (optional, post-MVP) | ⏳ Deferred | As expected | - -### Short Link Features - -| Spec Requirement | Status | Notes | -|-----------------|--------|-------| -| UTM builder (preset templates) | ❌ Missing | Spec mentions UTM builder for Pro plan | -| Destination URL allowlist/denylist | ❌ Missing | Abuse prevention not implemented | -| Soft delete for links | ❌ Missing | Currently using hard delete | - -### QR Code Designer - -| Spec Requirement | Status | Notes | -|-----------------|--------|-------| -| Shape presets (module shapes) | ✅ Complete | Square, Rounded, Dots module shapes supported | -| Eye shape customization | ✅ Complete | Square, Rounded, Circle eye shapes supported | -| Logo upload integration | ✅ Complete | Upload new or select from existing assets | -| Logo size + margin controls | ⚠️ Partial | Fixed 20% size, no user controls | -| Print-ready options ("high contrast" toggle) | ❌ Missing | No print optimization features | - -### Analytics & Tracking - -| Spec Requirement | Status | Notes | -|-----------------|--------|-------| -| Geo (country) breakdown | ✅ Complete | MaxMind GeoIP2 integrated, UI with country flags | -| Per-QR analytics endpoint | ❌ Missing | Spec: `GET /analytics/qrcode/{id}` - only link analytics exist | -| Scan vs Click distinction via `?qr=` param | ⚠️ Partial | Event type exists but QR export doesn't append `?qr=` to URLs | -| Custom date range filter | ❌ Missing | Only 24h/7d/30d implemented, spec mentions custom range | -| Monthly IP salt rotation | ❌ Missing | Spec requires rotating salt for privacy compliance | -| Event retention configuration per plan | ❌ Missing | No retention policy or cleanup jobs | - -### Admin & Quotas - -| Spec Requirement | Status | Notes | -|-----------------|--------|-------| -| Subscription status display | ❌ Missing | Plan field exists on Workspace but no UI | -| Usage quotas enforcement | ❌ Missing | No limits enforced for links/QRs/events/domains | -| Upgrade prompts | ❌ Missing | No paywall or upgrade flows | - -### Security & Non-Functional - -| Spec Requirement | Status | Notes | -|-----------------|--------|-------| -| Rate limiting on public endpoints | ❌ Missing | Critical for redirect endpoint | -| CORS configuration | ❌ Missing | Needs proper configuration | -| Strict CSP headers | ❌ Missing | App pages have no CSP | -| Request logging | ❌ Missing | No structured logging | -| Error handling middleware | ❌ Missing | No global error handler | - -### Frontend UI Pages - -| Spec Requirement | Status | Notes | -|-----------------|--------|-------| -| Forgot password page | ✅ Complete | Full UI with success state | -| Password reset page | ✅ Complete | Full UI with token validation and success state | -| Projects list UI | ❌ Missing | Backend CRUD complete, no frontend | -| Domains page (add/verify) | ❌ Missing | Backend complete, no frontend | -| Workspace switcher (full UI) | ⚠️ Partial | Basic switcher exists, no create/manage UI | -| Per-QR analytics view | ❌ Missing | Only per-link analytics in UI | - -### Email System - -| Spec Requirement | Status | Notes | -|-----------------|--------|-------| -| Email service integration | ❌ Missing | No email provider configured | -| Email verification emails | ❌ Missing | No templates or sending logic | -| Password reset emails | ❌ Missing | Token generated but not emailed | -| Email templates | ❌ Missing | No templating system | - -### Background Jobs - -| Spec Requirement | Status | Notes | -|-----------------|--------|-------| -| Domain verification checks | ❌ Missing | Only manual verification, no periodic checks | -| Event enrichment (geo/device) | ✅ Complete | Device parsing and GeoIP country lookup done | -| Cleanup & retention tasks | ❌ Missing | No scheduled cleanup for old events | - -### API Surface Gaps - -| Endpoint (from spec) | Status | -|---------------------|--------| -| `GET /analytics/qrcode/{id}` | ❌ Missing | -| Account settings endpoints | ❌ Missing | -| Usage/quota endpoints | ❌ Missing | +- **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 --- -## Priority Gap Resolution +## API Endpoints Summary -### High Priority (MVP Blockers) +### 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 | -1. **Email system** - Verification and password reset cannot work without email -2. **Rate limiting** - Security risk without it on public redirect -3. **QR scan tracking** - QR exports need `?qr=` param for scan attribution -4. ~~**Geo breakdown** - GeoIP integration for country-level analytics~~ ✅ Complete -5. **Projects UI** - Backend exists, needs frontend +### 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 | -### Medium Priority (MVP Polish) +### 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 | -6. **Account settings page** - Users need to update profile -7. **Domains UI** - Backend exists, needs frontend -8. **Usage quotas** - Enforce plan limits -9. ~~**QR shape presets** - More customization options~~ ✅ Complete (Square, Rounded, Dots) -10. **Custom date range** - Analytics flexibility +### 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 | -### Lower Priority (Post-MVP) +### 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 | -11. UTM builder -12. Soft delete for links -13. Print-ready QR options -14. SSO integration -15. Stripe payments +### 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) | -## Notes +### Analytics +| Method | Path | Description | +|--------|------|-------------| +| GET | /workspaces/{id}/analytics | Workspace analytics | -- Backend uses FastEndpoints (not traditional MVC controllers) -- Vertical slice architecture: features in `src/api/Features/{Feature}/` -- All endpoints require JWT auth except public redirect -- Default domain: use app's domain until custom domains implemented +### 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 |