task_id: task_create_api_generate_app entity_id: api_generate_app generated_at: '2025-12-19T06:08:12.163139' workflow_version: v001 target: type: api definition: id: api_generate_app method: POST path: /api/apps/generate summary: Generate app from recording description: Trigger AI app generation based on recording summary (wake word detection) tags: - apps - ai path_params: [] query_params: [] request_body: content_type: application/json schema: type: object properties: - name: recording_id type: uuid required: true description: Source recording ID example: recording_id: rec-123 responses: - status: 201 description: App generation started schema: type: object properties: - name: id type: uuid - name: recording_id type: uuid - name: status type: string example: id: app-123 recording_id: rec-123 status: generating - status: 400 description: Recording has no summary schema: type: object properties: - name: error type: string example: error: Recording summary not available - status: 404 description: Recording not found schema: type: object properties: - name: error type: string example: error: Recording not found depends_on_models: - model_generated_app - model_recording depends_on_apis: - api_summarize_recording auth: required: true roles: [] related: models: - id: model_generated_app definition: &id002 id: model_generated_app name: GeneratedApp description: AI-generated application from recording content table_name: generated_apps fields: - name: id type: uuid constraints: - primary_key description: Unique app identifier - name: user_id type: uuid constraints: - foreign_key - not_null - indexed description: Owner of this app - name: recording_id type: uuid constraints: - foreign_key - not_null - indexed description: Source recording that triggered generation - name: title type: string constraints: - not_null description: App title from AI analysis - name: description type: text constraints: [] description: App description - name: html_content type: text constraints: - not_null description: Complete HTML/CSS/JS for iframe rendering - name: prd_content type: text constraints: [] description: Product Requirements Document (PRD) generated by AI - name: ui_ux_design type: text constraints: [] description: UI/UX design notes from AI - name: app_type type: string constraints: [] description: Type of app determined by AI (e.g., todo, calculator, form) - name: status type: enum enum_values: - generating - completed - failed constraints: - not_null - default default: generating description: Generation status relations: - type: belongs_to target: model_user foreign_key: user_id on_delete: cascade - type: belongs_to target: model_recording foreign_key: recording_id on_delete: cascade indexes: - fields: - user_id - created_at unique: false name: idx_apps_user_created - fields: - recording_id unique: false name: idx_apps_recording timestamps: true soft_delete: false validations: [] external: false - id: model_recording definition: &id003 id: model_recording name: Recording description: Voice recording with transcript and summary table_name: recordings fields: - name: id type: uuid constraints: - primary_key description: Unique recording identifier - name: user_id type: uuid constraints: - foreign_key - not_null - indexed description: Owner of this recording - name: title type: string constraints: - not_null description: Recording title (auto-generated or user-edited) - name: audio_file_path type: string constraints: - not_null description: Path to audio file in MinIO/S3 - name: duration type: integer constraints: - not_null description: Recording duration in seconds - name: transcript type: text constraints: [] description: Full transcript from Whisper STT - name: summary type: text constraints: [] description: AI-generated summary from Gemini - name: is_transcribing type: boolean constraints: - not_null - default default: false description: Whether currently transcribing relations: - type: belongs_to target: model_user foreign_key: user_id on_delete: cascade indexes: - fields: - user_id - created_at unique: false name: idx_recordings_user_created timestamps: true soft_delete: false validations: - field: duration rule: min:1 message: Duration must be at least 1 second external: false apis: - id: api_summarize_recording definition: &id001 id: api_summarize_recording method: POST path: /api/recordings/[id]/summarize summary: Summarize recording description: Use Gemini to generate summary from transcript tags: - recordings - ai path_params: - name: id type: uuid description: Recording ID query_params: [] request_body: content_type: application/json schema: type: object properties: [] responses: - status: 200 description: Summary generated schema: type: object properties: - name: recording_id type: uuid - name: summary type: string example: recording_id: rec-123 summary: Meeting discussion about Q1 goals... - status: 400 description: No transcript available schema: type: object properties: - name: error type: string example: error: Transcript not available - status: 404 description: Recording not found schema: type: object properties: - name: error type: string example: error: Recording not found depends_on_models: - model_recording depends_on_apis: - api_transcribe_recording auth: required: true roles: [] external: false components: [] dependencies: entity_ids: - api_summarize_recording - model_generated_app - model_recording definitions: - id: api_summarize_recording type: api definition: *id001 external: false - id: model_generated_app type: model definition: *id002 external: false - id: model_recording type: model definition: *id003 external: false files: to_create: - app/api/apps/generate/route.ts reference: [] acceptance: - criterion: POST /api/apps/generate returns success response verification: curl -X POST /api/apps/generate - criterion: Request validation implemented verification: Test with invalid data - criterion: Error responses match contract verification: Test error scenarios