Implements all 5 phases of Foundary Studio backend:
Phase 1: Chat Persistence (8 API endpoints)
- Conversations and messages with proper cascading deletes
- PostgreSQL schema with auto-update triggers
- Full CRUD operations with structured logging
Phase 2: Blueprint Entity (5 API endpoints)
- JSONB spec storage with GIN indexes
- Flexible structured data for project specifications
- Version-controlled blueprint management
Phase 3: Architect Service (3 API endpoints)
- Conversational AI orchestration with Claude
- Multi-turn dialogue with context building
- Blueprint spec extraction from conversations
Phase 4: Work Queue Integration
- Verified existing endpoint compatibility
Phase 5: Structured Questions (6 API endpoints)
- Four question types: text, choice, multichoice, yesno
- Answer validation with proper constraints
- Conversation-linked Q&A flow
Architecture:
- Textbook hexagonal architecture (domain → port → adapter → service → handler)
- Zero external dependencies in domain layer
- Consistent error handling with proper wrapping
- Auth scopes on all routes (projects:read, projects:execute)
- Structured logging with operation context and duration tracking
- NULL-safe DTO converters throughout
Database:
- 3 new migrations (019, 020, 021)
- UUIDs for all primary keys
- Proper foreign key constraints with ON DELETE CASCADE
- Optimized indexes including partial index for unanswered questions
- Auto-update triggers for timestamps
OpenAPI Documentation:
- Complete API documentation under 'Foundary' tag
- 22 new endpoints documented with examples
- Request/response schemas for all operations
Logging Improvements:
- Added operation field to all service logs
- Added duration_ms tracking for performance monitoring
- Log response_length instead of full response content
- Consistent use of logging field constants
- Execute-then-log pattern for delete operations
Files: 32 changed, 2800+ lines added
- 7 domain models
- 3 database migrations
- 3 port interfaces
- 3 postgres adapters
- 4 services (conversation, blueprint, question, architect)
- 4 handlers with DTOs
- OpenAPI documentation
- Integration in main.go
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
42 lines
1.3 KiB
Go
42 lines
1.3 KiB
Go
package handlers
|
|
|
|
import "github.com/orchard9/rdev/internal/domain"
|
|
|
|
// QuestionDTO is the data transfer object for questions.
|
|
type QuestionDTO struct {
|
|
ID string `json:"id"`
|
|
ConversationID string `json:"conversation_id"`
|
|
ProjectID string `json:"project_id"`
|
|
Type string `json:"type"`
|
|
Text string `json:"text"`
|
|
Choices []string `json:"choices,omitempty"`
|
|
Answer *string `json:"answer,omitempty"`
|
|
AnswerChoices []string `json:"answer_choices,omitempty"`
|
|
Metadata map[string]string `json:"metadata,omitempty"`
|
|
CreatedAt string `json:"created_at"`
|
|
AnsweredAt *string `json:"answered_at,omitempty"`
|
|
}
|
|
|
|
func toQuestionDTO(q *domain.Question) *QuestionDTO {
|
|
if q == nil {
|
|
return nil
|
|
}
|
|
dto := &QuestionDTO{
|
|
ID: string(q.ID),
|
|
ConversationID: string(q.ConversationID),
|
|
ProjectID: q.ProjectID,
|
|
Type: string(q.Type),
|
|
Text: q.Text,
|
|
Choices: q.Choices,
|
|
Answer: q.Answer,
|
|
AnswerChoices: q.AnswerChoices,
|
|
Metadata: q.Metadata,
|
|
CreatedAt: q.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
|
|
}
|
|
if q.AnsweredAt != nil {
|
|
ts := q.AnsweredAt.Format("2006-01-02T15:04:05Z07:00")
|
|
dto.AnsweredAt = &ts
|
|
}
|
|
return dto
|
|
}
|