File size: 17,404 Bytes
310260a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
# KIro Todo API Documentation

**Version**: 1.0.0
**Base URL**: `http://localhost:8001`
**Authentication**: JWT Bearer Token

---

## Table of Contents

1. [Overview](#overview)
2. [Authentication](#authentication)
3. [Task Management](#task-management)
4. [Data Models](#data-models)
5. [Error Handling](#error-handling)
6. [Security](#security)
7. [Examples](#examples)

---

## Overview

The KIro Todo API is a RESTful API built with FastAPI that provides secure, multi-user task management with complete data isolation. Each user can only access their own tasks, enforced through JWT authentication and database-level filtering.

**Key Features:**
- JWT-based authentication
- User-scoped data isolation
- Complete CRUD operations for tasks
- Task completion tracking
- Comprehensive error handling
- Automatic timestamp management

---

## Authentication

All task endpoints require a valid JWT token in the `Authorization` header.

### User Signup

Create a new user account.

**Endpoint:** `POST /api/auth/signup`

**Request Body:**
```json
{
  "email": "user@example.com",
  "password": "SecurePass123"
}
```

**Response:** `201 Created`
```json
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "user": {
    "id": 1,
    "email": "user@example.com"
  }
}
```

**Validation Rules:**
- Email must be valid format
- Password minimum 8 characters
- Password must contain: uppercase, lowercase, number
- Email must be unique

**Error Responses:**
- `400 Bad Request` - Invalid email format or weak password
- `409 Conflict` - Email already exists

---

### User Signin

Authenticate an existing user.

**Endpoint:** `POST /api/auth/signin`

**Request Body:**
```json
{
  "email": "user@example.com",
  "password": "SecurePass123"
}
```

**Response:** `200 OK`
```json
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "user": {
    "id": 1,
    "email": "user@example.com"
  }
}
```

**Error Responses:**
- `401 Unauthorized` - Invalid credentials

---

## Task Management

All task endpoints require authentication via JWT token.

**Authentication Header:**
```
Authorization: Bearer <your_jwt_token>
```

---

### List All Tasks

Retrieve all tasks for the authenticated user.

**Endpoint:** `GET /api/tasks`

**Headers:**
```
Authorization: Bearer <token>
```

**Response:** `200 OK`
```json
[
  {
    "id": 1,
    "title": "Complete project documentation",
    "description": "Write comprehensive API docs",
    "completed": false,
    "user_id": 1,
    "created_at": "2026-02-03T10:30:00Z",
    "updated_at": "2026-02-03T10:30:00Z"
  },
  {
    "id": 2,
    "title": "Review pull requests",
    "description": null,
    "completed": true,
    "user_id": 1,
    "created_at": "2026-02-03T09:15:00Z",
    "updated_at": "2026-02-03T11:45:00Z"
  }
]
```

**Query Parameters:** None

**Notes:**
- Returns only tasks owned by authenticated user
- Ordered by creation date (newest first)
- Empty array if user has no tasks

---

### Create Task

Create a new task for the authenticated user.

**Endpoint:** `POST /api/tasks`

**Headers:**
```
Authorization: Bearer <token>
Content-Type: application/json
```

**Request Body:**
```json
{
  "title": "Buy groceries",
  "description": "Milk, eggs, bread, and coffee"
}
```

**Response:** `201 Created`
```json
{
  "id": 3,
  "title": "Buy groceries",
  "description": "Milk, eggs, bread, and coffee",
  "completed": false,
  "user_id": 1,
  "created_at": "2026-02-03T12:00:00Z",
  "updated_at": "2026-02-03T12:00:00Z"
}
```

**Field Requirements:**
- `title` (required): 1-200 characters, cannot be empty or whitespace
- `description` (optional): 0-2000 characters, can be null

**Error Responses:**
- `400 Bad Request` - Missing or empty title
- `401 Unauthorized` - Invalid or missing token

**Notes:**
- `user_id` is automatically set from JWT token
- `completed` defaults to `false`
- Timestamps are automatically generated

---

### Get Single Task

Retrieve a specific task by ID.

**Endpoint:** `GET /api/tasks/{task_id}`

**Headers:**
```
Authorization: Bearer <token>
```

**Path Parameters:**
- `task_id` (integer): The task ID

**Response:** `200 OK`
```json
{
  "id": 1,
  "title": "Complete project documentation",
  "description": "Write comprehensive API docs",
  "completed": false,
  "user_id": 1,
  "created_at": "2026-02-03T10:30:00Z",
  "updated_at": "2026-02-03T10:30:00Z"
}
```

**Error Responses:**
- `401 Unauthorized` - Invalid or missing token
- `403 Forbidden` - Task belongs to another user
- `404 Not Found` - Task does not exist

**Security:**
- Ownership is verified before returning task
- Users cannot access other users' tasks

---

### Update Task

Update an existing task's title and/or description.

**Endpoint:** `PUT /api/tasks/{task_id}`

**Headers:**
```
Authorization: Bearer <token>
Content-Type: application/json
```

**Path Parameters:**
- `task_id` (integer): The task ID

**Request Body:**
```json
{
  "title": "Complete project documentation (Updated)",
  "description": "Write comprehensive API docs with examples"
}
```

**Partial Update Supported:**
```json
{
  "title": "New title only"
}
```

**Response:** `200 OK`
```json
{
  "id": 1,
  "title": "Complete project documentation (Updated)",
  "description": "Write comprehensive API docs with examples",
  "completed": false,
  "user_id": 1,
  "created_at": "2026-02-03T10:30:00Z",
  "updated_at": "2026-02-03T12:30:00Z"
}
```

**Field Requirements:**
- `title` (optional): If provided, 1-200 characters, cannot be empty
- `description` (optional): If provided, 0-2000 characters

**Error Responses:**
- `400 Bad Request` - Empty title provided
- `401 Unauthorized` - Invalid or missing token
- `403 Forbidden` - Task belongs to another user
- `404 Not Found` - Task does not exist

**Notes:**
- Only provided fields are updated
- `updated_at` timestamp is automatically updated
- Ownership is verified before update

---

### Delete Task

Permanently delete a task.

**Endpoint:** `DELETE /api/tasks/{task_id}`

**Headers:**
```
Authorization: Bearer <token>
```

**Path Parameters:**
- `task_id` (integer): The task ID

**Response:** `200 OK`
```json
{
  "message": "Task deleted successfully"
}
```

**Error Responses:**
- `401 Unauthorized` - Invalid or missing token
- `403 Forbidden` - Task belongs to another user
- `404 Not Found` - Task does not exist

**Notes:**
- Deletion is permanent (no soft delete)
- Ownership is verified before deletion

---

### Toggle Task Completion

Toggle a task's completion status (complete ↔ incomplete).

**Endpoint:** `PATCH /api/tasks/{task_id}/complete`

**Headers:**
```
Authorization: Bearer <token>
```

**Path Parameters:**
- `task_id` (integer): The task ID

**Request Body:** None

**Response:** `200 OK`
```json
{
  "id": 1,
  "title": "Complete project documentation",
  "description": "Write comprehensive API docs",
  "completed": true,
  "user_id": 1,
  "created_at": "2026-02-03T10:30:00Z",
  "updated_at": "2026-02-03T13:00:00Z"
}
```

**Behavior:**
- `completed: false` β†’ `completed: true`
- `completed: true` β†’ `completed: false`

**Error Responses:**
- `401 Unauthorized` - Invalid or missing token
- `403 Forbidden` - Task belongs to another user
- `404 Not Found` - Task does not exist

**Notes:**
- `updated_at` timestamp is automatically updated
- Ownership is verified before toggle

---

## Data Models

### User

```typescript
{
  id: number;              // Auto-generated primary key
  email: string;           // Unique, valid email format
  password_hash: string;   // Bcrypt hashed password (never exposed in API)
  created_at: datetime;    // Auto-generated timestamp
}
```

### Task

```typescript
{
  id: number;              // Auto-generated primary key
  title: string;           // Required, 1-200 characters
  description: string | null;  // Optional, 0-2000 characters
  completed: boolean;      // Default: false
  user_id: number;         // Foreign key to User (from JWT)
  created_at: datetime;    // Auto-generated timestamp
  updated_at: datetime;    // Auto-updated on changes
}
```

### JWT Token Payload

```typescript
{
  user_id: number;         // User's database ID
  email: string;           // User's email
  exp: number;             // Token expiration timestamp
  iat: number;             // Token issued at timestamp
}
```

---

## Error Handling

All errors follow a consistent format:

```json
{
  "error": "Detailed error message",
  "message": "User-friendly message",
  "details": null
}
```

### HTTP Status Codes

| Code | Meaning | When Used |
|------|---------|-----------|
| `200` | OK | Successful GET, PUT, PATCH, DELETE |
| `201` | Created | Successful POST (resource created) |
| `400` | Bad Request | Invalid input, validation failure |
| `401` | Unauthorized | Missing or invalid JWT token |
| `403` | Forbidden | Valid token but insufficient permissions |
| `404` | Not Found | Resource does not exist |
| `409` | Conflict | Resource already exists (e.g., duplicate email) |
| `500` | Internal Server Error | Unexpected server error |

### Common Error Scenarios

**Missing Authentication:**
```json
{
  "error": "Not authenticated",
  "message": "Authentication is required to access this resource",
  "details": null
}
```

**Invalid Token:**
```json
{
  "error": "Invalid token",
  "message": "Authentication is required to access this resource",
  "details": null
}
```

**Accessing Another User's Task:**
```json
{
  "error": "You do not have permission to access this task",
  "message": "You do not have permission to access this resource",
  "details": null
}
```

**Task Not Found:**
```json
{
  "error": "Task not found",
  "message": "The requested resource was not found",
  "details": null
}
```

**Validation Error:**
```json
{
  "error": "Title is required and cannot be empty",
  "message": "The request contains invalid data",
  "details": null
}
```

---

## Security

### Authentication Flow

1. **User Registration/Login:**
   - User provides email and password
   - Backend validates credentials
   - Backend generates JWT token with user_id
   - Token returned to client

2. **Authenticated Requests:**
   - Client includes token in `Authorization: Bearer <token>` header
   - Backend verifies token signature
   - Backend extracts `user_id` from token payload
   - Backend uses `user_id` for all database queries

### Security Guarantees

βœ… **User Identity from JWT Only:**
- User ID is NEVER accepted from client input
- All user identification comes from verified JWT token
- Prevents user impersonation attacks

βœ… **Complete Data Isolation:**
- All database queries filtered by authenticated `user_id`
- Users cannot view, edit, or delete other users' tasks
- Ownership verified on every operation

βœ… **Password Security:**
- Passwords hashed with bcrypt before storage
- Plain-text passwords never stored
- Password hashes never exposed in API responses

βœ… **SQL Injection Prevention:**
- All queries use SQLModel ORM with parameterization
- No raw SQL with string concatenation

βœ… **CORS Protection:**
- CORS middleware configured with allowed origins
- Prevents unauthorized cross-origin requests

### Token Management

**Token Expiration:** 7 days (168 hours)

**Token Format:**
```
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJleHAiOjE3MDcwNTI4MDB9.signature
```

**Token Verification:**
- Signature verified using `JWT_SECRET`
- Expiration checked on every request
- Invalid tokens rejected with 401 Unauthorized

---

## Examples

### Complete Workflow Example

#### 1. Create Account

```bash
curl -X POST http://localhost:8001/api/auth/signup \
  -H "Content-Type: application/json" \
  -d '{
    "email": "john@example.com",
    "password": "SecurePass123"
  }'
```

**Response:**
```json
{
  "access_token": "eyJhbGc...",
  "token_type": "bearer",
  "user": {
    "id": 1,
    "email": "john@example.com"
  }
}
```

#### 2. Create Task

```bash
curl -X POST http://localhost:8001/api/tasks \
  -H "Authorization: Bearer eyJhbGc..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Learn FastAPI",
    "description": "Build a REST API with authentication"
  }'
```

**Response:**
```json
{
  "id": 1,
  "title": "Learn FastAPI",
  "description": "Build a REST API with authentication",
  "completed": false,
  "user_id": 1,
  "created_at": "2026-02-03T14:00:00Z",
  "updated_at": "2026-02-03T14:00:00Z"
}
```

#### 3. List Tasks

```bash
curl -X GET http://localhost:8001/api/tasks \
  -H "Authorization: Bearer eyJhbGc..."
```

**Response:**
```json
[
  {
    "id": 1,
    "title": "Learn FastAPI",
    "description": "Build a REST API with authentication",
    "completed": false,
    "user_id": 1,
    "created_at": "2026-02-03T14:00:00Z",
    "updated_at": "2026-02-03T14:00:00Z"
  }
]
```

#### 4. Mark Task Complete

```bash
curl -X PATCH http://localhost:8001/api/tasks/1/complete \
  -H "Authorization: Bearer eyJhbGc..."
```

**Response:**
```json
{
  "id": 1,
  "title": "Learn FastAPI",
  "description": "Build a REST API with authentication",
  "completed": true,
  "user_id": 1,
  "created_at": "2026-02-03T14:00:00Z",
  "updated_at": "2026-02-03T14:30:00Z"
}
```

#### 5. Update Task

```bash
curl -X PUT http://localhost:8001/api/tasks/1 \
  -H "Authorization: Bearer eyJhbGc..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Master FastAPI",
    "description": "Build production-ready APIs"
  }'
```

#### 6. Delete Task

```bash
curl -X DELETE http://localhost:8001/api/tasks/1 \
  -H "Authorization: Bearer eyJhbGc..."
```

**Response:**
```json
{
  "message": "Task deleted successfully"
}
```

---

### JavaScript/TypeScript Example

```typescript
// API Client Configuration
const API_BASE_URL = 'http://localhost:8001';
let authToken: string | null = null;

// Signup
async function signup(email: string, password: string) {
  const response = await fetch(`${API_BASE_URL}/api/auth/signup`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, password })
  });

  const data = await response.json();
  authToken = data.access_token;
  return data;
}

// Create Task
async function createTask(title: string, description?: string) {
  const response = await fetch(`${API_BASE_URL}/api/tasks`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${authToken}`
    },
    body: JSON.stringify({ title, description })
  });

  return response.json();
}

// List Tasks
async function listTasks() {
  const response = await fetch(`${API_BASE_URL}/api/tasks`, {
    headers: {
      'Authorization': `Bearer ${authToken}`
    }
  });

  return response.json();
}

// Toggle Task Completion
async function toggleTaskComplete(taskId: number) {
  const response = await fetch(`${API_BASE_URL}/api/tasks/${taskId}/complete`, {
    method: 'PATCH',
    headers: {
      'Authorization': `Bearer ${authToken}`
    }
  });

  return response.json();
}

// Delete Task
async function deleteTask(taskId: number) {
  const response = await fetch(`${API_BASE_URL}/api/tasks/${taskId}`, {
    method: 'DELETE',
    headers: {
      'Authorization': `Bearer ${authToken}`
    }
  });

  return response.json();
}
```

---

## Testing the API

### Using Swagger UI

FastAPI provides interactive API documentation:

1. Start the backend server
2. Open browser to: http://localhost:8001/docs
3. Click "Authorize" button
4. Enter JWT token from signup/signin response
5. Test endpoints interactively

### Using Postman

1. Import the API endpoints
2. Set `Authorization` header: `Bearer <token>`
3. Set `Content-Type` header: `application/json`
4. Test each endpoint

### Using curl

See examples above for complete curl commands.

---

## Rate Limiting & Performance

**Current Implementation:**
- No rate limiting (suitable for development/hackathon)
- Database connection pooling via Neon PostgreSQL
- Async/await for non-blocking I/O

**Production Recommendations:**
- Add rate limiting middleware
- Implement request caching
- Add database query optimization
- Monitor API performance metrics

---

## Support & Troubleshooting

**Common Issues:**

1. **401 Unauthorized on all requests**
   - Check token is included in Authorization header
   - Verify token format: `Bearer <token>`
   - Ensure JWT_SECRET matches between backend and frontend

2. **403 Forbidden when accessing task**
   - Task belongs to another user
   - Verify you're using correct user's token

3. **CORS errors from frontend**
   - Check CORS_ORIGINS in backend .env
   - Ensure frontend URL is in allowed origins list

4. **Database connection errors**
   - Verify DATABASE_URL in .env
   - Check Neon PostgreSQL is accessible
   - Test connection with database client

---

## API Versioning

**Current Version:** v1.0.0

**Endpoint Prefix:** `/api/`

**Future Versioning Strategy:**
- Breaking changes will use new prefix: `/api/v2/`
- Current endpoints will remain stable
- Deprecation notices will be provided in advance

---

## Changelog

### v1.0.0 (2026-02-03)
- Initial release
- User authentication (signup, signin)
- Task CRUD operations
- Task completion tracking
- JWT-based security
- Complete data isolation

---

**Last Updated:** 2026-02-03
**Maintained By:** KIro Todo Development Team