User
Theusers table stores account credentials and profile information. Passwords are never stored in plaintext — they are hashed with bcrypt before being persisted.
The
password_hash field is never included in API responses. Use to_dict() output shapes shown below to understand what the API returns.Fields
Auto-incremented primary key.
Unique username. Must be 3–80 characters and contain only letters, digits, underscores, and hyphens. Indexed for fast lookups.
Unique email address. Maximum 120 characters. Stored in lowercase. Indexed for fast lookups.
bcrypt hash of the user’s password. Maximum 255 characters. Never returned in API responses.
Optional first name. Maximum 50 characters.
Optional last name. Maximum 50 characters.
Whether the account is active. Defaults to
true. Inactive users cannot authenticate.Foreign key referencing
roles.id. Every user must have a role.UTC timestamp of account creation.
UTC timestamp of the most recent update. Automatically updated by a database trigger on every
UPDATE.to_dict() output
The User model serializes to the following JSON shape. The role object is included by default and can be omitted when include_role=False.
The
full_name field is a computed property. It returns "{first_name} {last_name}" when both are set, and falls back to username otherwise.Task
Thetasks table is the core of the API. Each task belongs to a user and may have zero or more tags attached through the task_tags junction table.
Fields
Auto-incremented primary key.
Task title. Required. Maximum 200 characters.
Optional long-form description. Stored as
TEXT (unlimited length in Azure SQL). Maximum 5,000 characters enforced at the application layer.Current status of the task. Defaults to
pending.Priority level. Defaults to
medium.Optional deadline. Must be provided in ISO 8601 format (e.g.,
2024-12-31T23:59:59 or 2024-12-31T23:59:59Z).UTC timestamp of when the task status was set to
completed. Set automatically when the task is marked complete and cleared if status changes back.Foreign key referencing
users.id. Deletes cascade: removing a user removes all their tasks.UTC timestamp of task creation.
UTC timestamp of the most recent update. Automatically maintained by a database trigger.
Array of Tag objects associated with this task via the
task_tags junction table. See the Tag model for the shape of each object.to_dict() output
By default, tags are included and the full user object is omitted. Pass include_user=True to embed the user.
is_overdue and is_completed are computed properties. is_overdue is true when due_date is in the past and the task is not yet completed.Tag
Thetags table stores reusable labels that can be attached to any number of tasks. Tags are global — they are not scoped to individual users.
Fields
Auto-incremented primary key.
Unique tag name. Maximum 50 characters. Indexed. Names must be unique across the entire system.
Hex color code in
#RRGGBB format (e.g., #FF5733). Defaults to #808080 (gray). Must match the pattern ^#[0-9A-Fa-f]{6}$.Optional description of the tag’s purpose. Maximum 255 characters.
UTC timestamp of tag creation.
UTC timestamp of the most recent update.
to_dict() output
task_count is a computed property that counts the number of tasks currently associated with the tag. Pass include_task_count=False to to_dict() to omit it.Role
Theroles table supports role-based access control (RBAC). Two roles are seeded by default.
Fields
Auto-incremented primary key.
Unique role identifier. One of
admin or user.Human-readable description of the role’s permissions.
UTC timestamp of role creation.
Default roles
| Name | Description |
|---|---|
admin | Administrator role with full access to all resources |
user | Standard user role with access limited to their own resources |
RefreshToken
Therefresh_tokens table persists JWT refresh tokens so they can be explicitly revoked. All refresh tokens for a user are automatically revoked when the user changes their password.
Fields
Auto-incremented primary key.
Foreign key referencing
users.id. Deletes cascade: removing a user removes all their tokens.The raw JWT refresh token string. Maximum 500 characters. Unique and indexed.
Whether the token has been explicitly revoked (e.g., by logging out or changing password). Defaults to
false.UTC expiry datetime. Defaults to 30 days after creation (
JWT_REFRESH_TOKEN_EXPIRES=2592000).UTC timestamp of token creation.
Database schema
The following ER diagram shows all tables and their relationships. One-to-many relationships are denoted with< (many side).
task_tags junction table implements the many-to-many relationship between tasks and tags. Both foreign keys participate in a composite primary key. Deletes cascade from both sides.
Paginated response format
All list endpoints (tasks, tags, users) wrap their results in a standard pagination envelope. Thepagination object uses total_pages as the key (not pages).
Current page number (1-indexed). Defaults to
1.Number of items per page. Defaults to
10 (DEFAULT_PAGE_SIZE). Maximum 100 (MAX_PAGE_SIZE).Total number of items matching the current filters.
Total number of pages. Computed as
ceil(total / per_page).true when there is at least one more page after the current one.true when the current page is greater than 1.