feat: initial HarborForge project structure

- Docker Compose with MySQL + FastAPI backend
- Issue model with RESOLUTION type (for agent deadlock resolution)
- Project, User, Comment models
- Basic CRUD API endpoints
- .env.example for configuration
This commit is contained in:
root
2026-02-21 08:02:32 +00:00
parent 054eed50e9
commit a557ab6f4a
14 changed files with 644 additions and 0 deletions

View File

@@ -0,0 +1,165 @@
from pydantic import BaseModel
from typing import Optional, List
from datetime import datetime
from enum import Enum
class IssueTypeEnum(str, Enum):
TASK = "task"
STORY = "story"
TEST = "test"
RESOLUTION = "resolution"
class IssueStatusEnum(str, Enum):
OPEN = "open"
IN_PROGRESS = "in_progress"
RESOLVED = "resolved"
CLOSED = "closed"
BLOCKED = "blocked"
class IssuePriorityEnum(str, Enum):
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
CRITICAL = "critical"
# Issue schemas
class IssueBase(BaseModel):
title: str
description: Optional[str] = None
issue_type: IssueTypeEnum = IssueTypeEnum.TASK
priority: IssuePriorityEnum = IssuePriorityEnum.MEDIUM
tags: Optional[str] = None
depends_on_id: Optional[int] = None
class IssueCreate(IssueBase):
project_id: int
reporter_id: int
assignee_id: Optional[int] = None
# Resolution specific
resolution_summary: Optional[str] = None
positions: Optional[str] = None
pending_matters: Optional[str] = None
class IssueUpdate(BaseModel):
title: Optional[str] = None
description: Optional[str] = None
status: Optional[IssueStatusEnum] = None
priority: Optional[IssuePriorityEnum] = None
assignee_id: Optional[int] = None
tags: Optional[str] = None
depends_on_id: Optional[int] = None
# Resolution specific
resolution_summary: Optional[str] = None
positions: Optional[str] = None
pending_matters: Optional[str] = None
class IssueResponse(IssueBase):
id: int
status: IssueStatusEnum
project_id: int
reporter_id: int
assignee_id: Optional[int]
resolution_summary: Optional[str]
positions: Optional[str]
pending_matters: Optional[str]
created_at: datetime
updated_at: Optional[datetime]
class Config:
from_attributes = True
# Comment schemas
class CommentBase(BaseModel):
content: str
class CommentCreate(CommentBase):
issue_id: int
author_id: int
class CommentUpdate(BaseModel):
content: Optional[str] = None
class CommentResponse(CommentBase):
id: int
issue_id: int
author_id: int
created_at: datetime
updated_at: Optional[datetime]
class Config:
from_attributes = True
# Project schemas
class ProjectBase(BaseModel):
name: str
description: Optional[str] = None
class ProjectCreate(ProjectBase):
owner_id: int
class ProjectUpdate(BaseModel):
name: Optional[str] = None
description: Optional[str] = None
class ProjectResponse(ProjectBase):
id: int
owner_id: int
created_at: datetime
class Config:
from_attributes = True
# User schemas
class UserBase(BaseModel):
username: str
email: str
full_name: Optional[str] = None
class UserCreate(UserBase):
password: Optional[str] = None
is_admin: bool = False
class UserResponse(UserBase):
id: int
is_active: bool
is_admin: bool
created_at: datetime
class Config:
from_attributes = True
# Project Member schemas
class ProjectMemberBase(BaseModel):
user_id: int
project_id: int
role: str = "dev"
class ProjectMemberCreate(ProjectMemberBase):
pass
class ProjectMemberResponse(ProjectMemberBase):
id: int
class Config:
from_attributes = True