openapi: 3.0.3
info:
  title: Thakur Ganeshsingh Journey Site API
  description: |
    RESTful API for the professional portfolio of Thakur Ganeshsingh, a Developer Advocate & Solutions Architect.
    
    This API provides endpoints for:
    - Contact form submissions
    - Newsletter subscription with Resend integration
    - LinkedIn OAuth integration and auto-publishing for blog posts
    - Email notifications to subscribers
    - Site information retrieval
    - Navigation data
    - Security health checks
    - LLM context data
    
    All endpoints include comprehensive security measures including CSRF protection, 
    input validation, rate limiting, and detailed logging.
    
    Built with Next.js 15 and TypeScript, deployed with security-first architecture.
  termsOfService: https://journey.thakurganeshsingh.com/terms
  contact:
    name: Thakur Ganeshsingh
    email: thakurg785@thakurganeshsingh.com
    url: https://journey.thakurganeshsingh.com
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT
  version: 2.0.0
externalDocs:
  description: Full Portfolio Documentation
  url: https://journey.thakurganeshsingh.com/docs
servers:
  - url: http://localhost:3000/api
    description: Production server
  - url: http://localhost:3000/api
    description: Development server
tags:
  - name: contact
    description: Contact form operations
    externalDocs:
      description: Contact page
      url: https://journey.thakurganeshsingh.com/contact
  - name: newsletter
    description: Newsletter subscription and management
    externalDocs:
      description: Newsletter signup
      url: https://journey.thakurganeshsingh.com/#newsletter
  - name: linkedin
    description: LinkedIn OAuth integration and content publishing
    externalDocs:
      description: LinkedIn Integration Guide
      url: https://journey.thakurganeshsingh.com/docs/linkedin-integration
  - name: publishing
    description: Content publishing and distribution
  - name: notifications
    description: Email notifications and subscriber management
  - name: navigation
    description: Site navigation and structure
  - name: site-info
    description: Portfolio and professional information
  - name: security
    description: Security monitoring and health checks
  - name: llm-context
    description: AI/LLM optimized content endpoints
paths:
  /newsletter:
    post:
      tags:
        - newsletter
      summary: Subscribe to newsletter
      description: |
        Subscribe to the portfolio newsletter using Resend email service.
        
        **Security Features:**
        - Rate limiting (5 requests per 15 minutes per IP)
        - Email validation with domain blocklist
        - Input sanitization and validation
        - CORS protection
        - Privacy-safe logging (email masking)
        
        **Email Features:**
        - Professional HTML welcome email
        - Mobile-responsive design
        - Easy one-click unsubscribe
        - Interest-based subscriptions
        
        **Powered by [Resend](https://resend.com)** for reliable email delivery.
      operationId: subscribeNewsletter
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NewsletterSubscriptionRequest'
            examples:
              basic_subscription:
                summary: Basic newsletter subscription
                value:
                  email: "john.doe@example.com"
                  source: "portfolio-website"
                  interests: ["blogs", "projects"]
              detailed_subscription:
                summary: Detailed subscription with all fields
                value:
                  email: "sarah.developer@company.com"
                  source: "linkedin-referral"
                  interests: ["blogs", "projects", "achievements", "general"]
      responses:
        '200':
          description: Successfully subscribed to newsletter
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NewsletterSubscriptionResponse'
              examples:
                success:
                  summary: Successful subscription
                  value:
                    success: true
                    message: "Successfully subscribed to newsletter!"
        '400':
          description: Bad request - Invalid email or validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                invalid_email:
                  summary: Invalid email format
                  value:
                    error: "Please provide a valid email address"
                blocked_domain:
                  summary: Blocked email domain
                  value:
                    error: "Email domain is not allowed"
        '429':
          description: Too many requests - Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                rate_limited:
                  summary: Rate limit exceeded
                  value:
                    error: "Too many requests. Please try again later."
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security: []
    options:
      tags:
        - newsletter
      summary: CORS preflight for newsletter subscription
      description: Handle CORS preflight requests for newsletter subscriptions
      operationId: newsletterOptions
      responses:
        '200':
          description: CORS preflight response
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
            Access-Control-Allow-Methods:
              schema:
                type: string
                example: "POST, OPTIONS"
            Access-Control-Allow-Headers:
              schema:
                type: string
                example: "Content-Type"

  /linkedin-auth:
    get:
      tags:
        - linkedin
      summary: Initiate LinkedIn OAuth flow
      description: |
        Initiates the LinkedIn OAuth 2.0 authorization flow for connecting a LinkedIn account.
        
        **Security Features:**
        - CSRF protection with state parameter
        - Secure redirect handling
        - OAuth 2.0 compliant flow
        
        **Required LinkedIn App Permissions:**
        - r_liteprofile (Read profile information)
        - w_member_social (Post on behalf of user)
        - w_organization_social (Post to company page)
        - r_organization_social (Read company page info)
        
        This endpoint redirects to LinkedIn's authorization page.
      operationId: linkedinAuth
      responses:
        '302':
          description: Redirect to LinkedIn OAuth authorization
          headers:
            Location:
              schema:
                type: string
                format: uri
                example: "https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=..."
            Set-Cookie:
              schema:
                type: string
                example: "linkedin-oauth-state=xyz123; HttpOnly; Secure; SameSite=Lax; Max-Age=600"
        '500':
          description: OAuth initiation failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /linkedin-callback:
    get:
      tags:
        - linkedin
      summary: LinkedIn OAuth callback handler
      description: |
        Handles the OAuth callback from LinkedIn after user authorization.
        
        **Security Features:**
        - State parameter verification (CSRF protection)
        - Authorization code validation
        - Secure token storage using JWT
        - Profile verification
        
        **Process Flow:**
        1. Validates state parameter against stored value
        2. Exchanges authorization code for access token
        3. Retrieves user profile information
        4. Stores encrypted tokens securely
        5. Redirects to admin dashboard with success/error status
        
        This endpoint is called automatically by LinkedIn after user authorization.
      operationId: linkedinCallback
      parameters:
        - name: code
          in: query
          required: true
          description: Authorization code from LinkedIn
          schema:
            type: string
            example: "AQTqhL5i2..."
        - name: state
          in: query
          required: true
          description: State parameter for CSRF protection
          schema:
            type: string
            example: "xyz123abc456"
        - name: error
          in: query
          required: false
          description: Error code if authorization failed
          schema:
            type: string
            example: "user_cancelled_authorize"
        - name: error_description
          in: query
          required: false
          description: Human-readable error description
          schema:
            type: string
            example: "The user cancelled the authorization process."
      responses:
        '302':
          description: Redirect to admin dashboard with result
          headers:
            Location:
              schema:
                type: string
                format: uri
                example: "https://journey.thakurganeshsingh.com/admin?success=linkedin_connected"
            Set-Cookie:
              schema:
                type: array
                items:
                  type: string
                example: 
                  - "linkedin-auth-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...; HttpOnly; Secure; SameSite=Lax; Max-Age=7776000"
                  - "linkedin-oauth-state=; Max-Age=0"

  /linkedin-status:
    get:
      tags:
        - linkedin
      summary: Check LinkedIn connection status
      description: |
        Returns the current LinkedIn authentication status and connection details.
        
        **Information Provided:**
        - Connection status (connected/disconnected)
        - Token expiry information
        - User profile details (if connected)
        - Company page information
        - Token refresh capability
        
        **Security Features:**
        - Secure token validation
        - Profile information sanitization
        - No sensitive data exposure in logs
        
        Used by the admin dashboard to display connection status and manage LinkedIn integration.
      operationId: linkedinStatus
      responses:
        '200':
          description: LinkedIn connection status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LinkedInStatusResponse'
              examples:
                connected:
                  summary: Successfully connected
                  value:
                    connected: true
                    expired: false
                    canRefresh: true
                    expiresAt: "2024-04-15T10:30:00Z"
                    profile:
                      firstName: "John"
                      lastName: "Doe"
                      id: "abc123xyz"
                    companyId: "12345678"
                disconnected:
                  summary: Not connected
                  value:
                    connected: false
                    message: "LinkedIn not authenticated"
                    authUrl: "/api/linkedin-auth"
                expired:
                  summary: Token expired
                  value:
                    connected: false
                    expired: true
                    message: "LinkedIn authentication expired"
                    authUrl: "/api/linkedin-auth"
        '500':
          description: Status check failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /blog-auto-publish:
    post:
      tags:
        - linkedin
        - publishing
      summary: Auto-publish blog posts to LinkedIn
      description: |
        Automatically scans for and publishes new blog posts to LinkedIn company page.
        
        **Security Features:**
        - Bearer token authentication required
        - Authorization header validation
        - Rate limiting protection
        - Input validation and sanitization
        
        **Publishing Logic:**
        - Scans content/blog directory for .mdx files
        - Only publishes blogs marked with `published: true`
        - Tracks published posts to prevent duplicates
        - Supports force republishing with forcePublish flag
        - Rich LinkedIn post formatting with hashtags
        
        **Typical Usage:**
        - Called automatically by GitHub Actions after deployment
        - Can be called manually from admin dashboard
        - Supports publishing specific blogs by slug
        
        **Integration:**
        This endpoint is typically called by the LinkedIn Auto-Publish GitHub Action
        after successful deployment to automatically share new blog content.
      operationId: blogAutoPublish
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BlogAutoPublishRequest'
            examples:
              auto_scan:
                summary: Scan and publish all new blogs
                value: {}
              specific_blog:
                summary: Publish specific blog
                value:
                  blogSlug: "my-latest-post"
                  forcePublish: false
              force_republish:
                summary: Force republish a blog
                value:
                  blogSlug: "important-update"
                  forcePublish: true
      responses:
        '200':
          description: Auto-publish completed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BlogAutoPublishResponse'
              examples:
                success:
                  summary: Successfully published blogs
                  value:
                    success: true
                    message: "Processed 5 blogs"
                    published: 2
                    errors: 0
                    results:
                      - slug: "new-blog-post"
                        published: true
                        linkedInUrl: "https://www.linkedin.com/feed/update/urn:li:share:123456"
                        title: "My New Blog Post"
                      - slug: "another-post"
                        published: true
                        linkedInUrl: "https://www.linkedin.com/feed/update/urn:li:share:789012"
                        title: "Another Great Post"
                no_new_posts:
                  summary: No new posts to publish
                  value:
                    success: true
                    message: "Processed 5 blogs"
                    published: 0
                    errors: 0
                    results: []
        '401':
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: "Unauthorized"
                message: "Valid AUTO_PUBLISH_SECRET required"
        '404':
          description: Blog directory not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Auto-publish failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - AutoPublishSecret: []
    get:
      tags:
        - linkedin
        - publishing
      summary: Get auto-publish status
      description: |
        Returns the current auto-publish status and statistics.
        
        **Information Provided:**
        - Number of blogs published to LinkedIn
        - List of published blog slugs
        - Last check timestamp
        
        Used for monitoring and dashboard display of publishing activity.
      operationId: getAutoPublishStatus
      responses:
        '200':
          description: Auto-publish status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AutoPublishStatusResponse'
              example:
                success: true
                publishedCount: 15
                publishedBlogs: ["blog-post-1", "blog-post-2", "latest-update"]
                lastCheck: "2024-01-15T10:30:00Z"
        '500':
          description: Failed to get status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /linkedin-publish:
    post:
      tags:
        - linkedin
        - publishing
      summary: Publish individual blog post to LinkedIn
      description: |
        Publishes a single blog post to LinkedIn company page with rich formatting.
        
        **Enhanced Features since Azure Functions migration:**
        - OAuth 2.0 token management with automatic refresh
        - Company page posting support
        - Rich post formatting with hashtags and links
        - Duplicate post prevention
        - Error handling and retry logic
        
        **Security Features:**
        - Bearer token authentication required
        - Rate limiting (5 posts per 24 hours)
        - Content validation and sanitization
        - URL validation and security checks
        
        **Features:**
        - Smart hashtag generation from tags
        - Professional post formatting
        - Error handling and retry logic
        - Publishing analytics and tracking
        
        **Authentication Required:** Internal API key for security.
        
        **LinkedIn API Integration:** Uses LinkedIn Share API v2 for optimal reach.
      operationId: publishToLinkedIn
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LinkedInPublishRequest'
            examples:
              blog_post:
                summary: Blog post publishing
                value:
                  title: "Building Scalable APIs with Next.js and TypeScript"
                  content: "In this comprehensive guide, we'll explore best practices for building robust, scalable APIs using Next.js 13+ and TypeScript..."
                  url: "https://journey.thakurganeshsingh.com/blog/scalable-apis-nextjs"
                  tags: ["nextjs", "typescript", "api", "webdev"]
                  coverImage: "https://journey.thakurganeshsingh.com/images/blog/api-cover.jpg"
      responses:
        '200':
          description: Successfully published to LinkedIn
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LinkedInPublishResponse'
              examples:
                success:
                  summary: Successful publication
                  value:
                    success: true
                    message: "Blog published to LinkedIn successfully!"
                    postId: "urn:li:share:1234567890"
        '400':
          description: Bad request - Invalid content or validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                invalid_url:
                  summary: Invalid URL provided
                  value:
                    error: "Valid URL is required"
                content_too_long:
                  summary: Content exceeds limit
                  value:
                    error: "Content must be under 3000 characters"
        '401':
          description: Unauthorized - Invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                unauthorized:
                  summary: Missing or invalid API key
                  value:
                    error: "Unauthorized"
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                daily_limit:
                  summary: Daily posting limit reached
                  value:
                    error: "Daily LinkedIn posting limit reached"
        '500':
          description: LinkedIn API error or internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - InternalAPIKey: []
    options:
      tags:
        - publishing
      summary: CORS preflight for LinkedIn publishing
      operationId: linkedinPublishOptions
      responses:
        '200':
          description: CORS preflight response

  /notify-subscribers:
    post:
      tags:
        - notifications
      summary: Send email notifications to subscribers
      description: |
        Send email notifications to newsletter subscribers about new content.
        
        **Security Features:**
        - Bearer token authentication required
        - Rate limiting (10 notifications per hour)
        - Content validation and sanitization
        - Subscriber filtering by interests
        
        **Email Features:**
        - Beautiful HTML templates with dynamic colors
        - Content-type specific styling (blog/project/achievement)
        - Mobile-responsive design
        - Cover image support
        - Professional unsubscribe process
        
        **Subscriber Management:**
        - Interest-based filtering
        - Privacy-safe logging
        - Delivery tracking and analytics
        
        **Powered by Resend** for high deliverability rates.
      operationId: notifySubscribers
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NotificationRequest'
            examples:
              blog_notification:
                summary: New blog post notification
                value:
                  type: "blog"
                  title: "Advanced React Patterns for 2024"
                  excerpt: "Explore the latest React patterns including Server Components, Suspense, and concurrent features for building modern web applications."
                  url: "https://journey.thakurganeshsingh.com/blog/react-patterns-2024"
                  coverImage: "https://journey.thakurganeshsingh.com/images/blog/react-patterns.jpg"
              project_notification:
                summary: New project announcement
                value:
                  type: "project"
                  title: "Open Source Developer Tools Suite"
                  excerpt: "Launched a comprehensive suite of developer productivity tools including API generators, code formatters, and documentation builders."
                  url: "https://journey.thakurganeshsingh.com/projects/dev-tools-suite"
      responses:
        '200':
          description: Notifications sent successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotificationResponse'
              examples:
                success:
                  summary: Successful notification delivery
                  value:
                    success: true
                    message: "Notification sent to 150 subscribers"
                    stats:
                      successful: 148
                      failed: 2
                      total: 150
        '400':
          description: Bad request - Invalid content type or validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                invalid_type:
                  summary: Invalid content type
                  value:
                    error: "Invalid content type"
        '401':
          description: Unauthorized - Invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                rate_limited:
                  summary: Notification rate limit exceeded
                  value:
                    error: "Rate limit exceeded. Too many notifications sent."
        '500':
          description: Internal server error or email delivery failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - InternalAPIKey: []
    options:
      tags:
        - notifications
      summary: CORS preflight for notifications
      operationId: notificationsOptions
      responses:
        '200':
          description: CORS preflight response

  /contact:
    post:
      tags:
        - contact
      summary: Submit contact form
      description: |
        Submit a contact form with comprehensive security validation.
        
        **Security Features:**
        - CSRF protection via origin validation
        - Input sanitization and validation
        - Rate limiting
        - Content length validation (2KB limit)
        - Email format validation
        - Security event logging
        
        **Note:** For static exports, this endpoint has limited functionality.
      operationId: submitContactForm
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContactFormRequest'
            examples:
              valid_submission:
                summary: Valid contact form submission
                value:
                  name: "John Doe"
                  email: "john.doe@example.com"
                  subject: "Collaboration Opportunity"
                  message: "Hi Ganesh, I'd like to discuss a potential collaboration on a developer advocacy project."
      responses:
        '200':
          description: Contact form submitted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactFormResponse'
              examples:
                success:
                  summary: Successful submission
                  value:
                    success: true
                    message: "Thank you for your message. I will get back to you soon!"
        '400':
          description: Bad request - Invalid input or validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                missing_fields:
                  summary: Missing required fields
                  value:
                    error: "Missing required fields"
                invalid_email:
                  summary: Invalid email format
                  value:
                    error: "Invalid email address"
                field_too_long:
                  summary: Field length exceeds limits
                  value:
                    error: "Field length exceeds limits"
        '403':
          description: Forbidden - CSRF protection or origin validation failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                invalid_origin:
                  summary: Invalid request origin
                  value:
                    error: "Invalid request origin"
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - OriginValidation: []
    options:
      tags:
        - contact
      summary: CORS preflight for contact form
      description: Handle CORS preflight requests for contact form submissions
      operationId: contactFormOptions
      responses:
        '200':
          description: CORS preflight response
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                example: "*"
            Access-Control-Allow-Methods:
              schema:
                type: string
                example: "POST, OPTIONS"
            Access-Control-Allow-Headers:
              schema:
                type: string
                example: "Content-Type"
            Access-Control-Max-Age:
              schema:
                type: string
                example: "86400"

  /navigation/docs:
    get:
      tags:
        - navigation
      summary: Get documentation navigation structure
      description: |
        Retrieve the navigation structure for the documentation section.
        
        Returns a hierarchical structure of documentation pages, categories,
        and their metadata for building navigation menus.
      operationId: getDocsNavigation
      responses:
        '200':
          description: Documentation navigation retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NavigationResponse'
              examples:
                docs_nav:
                  summary: Documentation navigation structure
                  value:
                    success: true
                    navigation:
                      - title: "Introduction"
                        href: "/docs/introduction"
                        description: "Get started with the documentation"
                      - title: "API Reference"
                        href: "/docs/api"
                        items:
                          - title: "Portfolio API"
                            href: "/docs/api/portfolio"
                          - title: "Authentication"
                            href: "/docs/api/api-authentication"
        '500':
          description: Failed to generate navigation
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ErrorResponse'
                  - type: object
                    properties:
                      navigation:
                        type: array
                        items: {}
                        example: []

  /navigation/blog:
    get:
      tags:
        - navigation
      summary: Get blog navigation structure
      description: Retrieve the navigation structure for the blog section
      operationId: getBlogNavigation
      responses:
        '200':
          description: Blog navigation retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NavigationResponse'
        '500':
          description: Failed to generate blog navigation
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ErrorResponse'
                  - type: object
                    properties:
                      navigation:
                        type: array
                        items: {}

  /site-info:
    get:
      tags:
        - site-info
      summary: Get comprehensive site and professional information
      description: |
        Retrieve comprehensive information about the portfolio site and professional details.
        
        **Includes:**
        - Personal and professional information
        - Technical skills and expertise
        - Career achievements and history
        - Education background
        - Site structure and pages
        - Social media links
        - AI/LLM specific metadata
        
        **Security Features:**
        - User agent validation to prevent malicious access
        - Security event logging
        - Rate limiting and monitoring
        
        **Caching:** 1 hour cache for performance optimization
      operationId: getSiteInfo
      responses:
        '200':
          description: Site information retrieved successfully
          headers:
            Cache-Control:
              description: Cache control header
              schema:
                type: string
                example: "public, max-age=3600"
            X-API-Version:
              description: API version
              schema:
                type: string
                example: "1.0"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SiteInfo'
        '403':
          description: Access denied - Invalid user agent or blocked request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                access_denied:
                  summary: Access denied
                  value:
                    error: "Access denied"
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - UserAgentValidation: []

  /security/health:
    get:
      tags:
        - security
      summary: Security health check endpoint
      description: |
        Check the security health status of the application.
        
        **Returns:**
        - Overall health status
        - Security feature status
        - Environment information
        - Application version
        
        **Security Features:**
        - Origin validation required
        - No caching for security reasons
        - Comprehensive logging
      operationId: getSecurityHealth
      responses:
        '200':
          description: Security health status
          headers:
            Cache-Control:
              description: No cache directive for security
              schema:
                type: string
                example: "no-store, no-cache, must-revalidate"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SecurityHealthResponse'
              examples:
                healthy:
                  summary: Healthy security status
                  value:
                    status: "healthy"
                    timestamp: "2024-01-15T10:30:00.000Z"
                    security:
                      headers_enabled: true
                      rate_limiting: true
                      input_validation: true
                      csrf_protection: true
                      xss_protection: true
                      content_security_policy: true
                    environment: "production"
                    version: "1.0.0"
        '401':
          description: Unauthorized - Origin validation failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Security health check failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - OriginValidation: []

  /llm-context:
    get:
      tags:
        - llm-context
      summary: Get LLM-optimized context information
      description: |
        Retrieve structured information optimized for Large Language Models (LLMs).
        
        This endpoint provides context about the portfolio owner that is specifically
        formatted and structured for AI consumption, including professional background,
        skills, achievements, and current role information.
      operationId: getLLMContext
      responses:
        '200':
          description: LLM context retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LLMContextResponse'
        '500':
          description: Failed to retrieve LLM context
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

components:
  schemas:
    NewsletterSubscriptionRequest:
      type: object
      required:
        - email
      properties:
        email:
          type: string
          format: email
          description: Valid email address for newsletter subscription
          example: "john.doe@example.com"
          maxLength: 254
        source:
          type: string
          description: Source of the subscription (e.g., website, linkedin, referral)
          example: "portfolio-website"
          maxLength: 100
          default: "portfolio-website"
        interests:
          type: array
          description: List of interests for targeted content
          items:
            type: string
            enum: ["blogs", "projects", "achievements", "general"]
          example: ["blogs", "projects"]
          default: ["general"]

    NewsletterSubscriptionResponse:
      type: object
      properties:
        success:
          type: boolean
          description: Indicates if subscription was successful
          example: true
        message:
          type: string
          description: Confirmation message
          example: "Successfully subscribed to newsletter!"

    LinkedInPublishRequest:
      type: object
      required:
        - title
        - url
      properties:
        title:
          type: string
          description: Blog post title
          example: "Building Scalable APIs with Next.js and TypeScript"
          maxLength: 300
        content:
          type: string
          description: Blog post content or excerpt
          example: "In this comprehensive guide, we'll explore best practices..."
          maxLength: 3000
        url:
          type: string
          format: uri
          description: URL to the full blog post
          example: "https://journey.thakurganeshsingh.com/blog/scalable-apis-nextjs"
        tags:
          type: array
          description: Tags for hashtag generation (max 10)
          items:
            type: string
          example: ["nextjs", "typescript", "api", "webdev"]
          maxItems: 10
        coverImage:
          type: string
          format: uri
          description: Optional cover image URL
          example: "https://journey.thakurganeshsingh.com/images/blog/api-cover.jpg"

    LinkedInPublishResponse:
      type: object
      properties:
        success:
          type: boolean
          description: Indicates if publishing was successful
          example: true
        message:
          type: string
          description: Confirmation message
          example: "Blog published to LinkedIn successfully!"
        postId:
          type: string
          description: LinkedIn post ID or URL
          example: "urn:li:share:1234567890"

    LinkedInStatusResponse:
      type: object
      properties:
        connected:
          type: boolean
          description: Whether LinkedIn is connected
          example: true
        expired:
          type: boolean
          description: Whether the token is expired
          example: false
        canRefresh:
          type: boolean
          description: Whether the token can be refreshed
          example: true
        expiresAt:
          type: string
          format: date-time
          description: Token expiry timestamp
          example: "2024-04-15T10:30:00Z"
        profile:
          type: object
          description: LinkedIn profile information (if connected)
          properties:
            firstName:
              type: string
              example: "John"
            lastName:
              type: string
              example: "Doe"
            id:
              type: string
              example: "abc123xyz"
        companyId:
          type: string
          description: LinkedIn company page ID
          example: "12345678"
        message:
          type: string
          description: Status message (if not connected)
          example: "LinkedIn not authenticated"
        authUrl:
          type: string
          description: URL to initiate authentication (if not connected)
          example: "/api/linkedin-auth"

    BlogAutoPublishRequest:
      type: object
      properties:
        blogSlug:
          type: string
          description: Specific blog slug to publish (optional)
          example: "my-latest-post"
        forcePublish:
          type: boolean
          description: Force republish even if already published
          example: false
          default: false

    BlogAutoPublishResponse:
      type: object
      properties:
        success:
          type: boolean
          description: Whether the operation was successful
          example: true
        message:
          type: string
          description: Summary message
          example: "Processed 5 blogs"
        published:
          type: integer
          description: Number of blogs published
          example: 2
        errors:
          type: integer
          description: Number of errors encountered
          example: 0
        results:
          type: array
          description: Detailed results for each blog processed
          items:
            type: object
            properties:
              slug:
                type: string
                description: Blog slug
                example: "new-blog-post"
              success:
                type: boolean
                description: Whether this blog was processed successfully
                example: true
              published:
                type: boolean
                description: Whether this blog was published
                example: true
              skipped:
                type: boolean
                description: Whether this blog was skipped
                example: false
              reason:
                type: string
                description: Reason for skipping (if skipped)
                example: "Already published to LinkedIn"
              error:
                type: string
                description: Error message (if failed)
                example: "LinkedIn API rate limit exceeded"
              linkedInUrl:
                type: string
                format: uri
                description: LinkedIn post URL (if published)
                example: "https://www.linkedin.com/feed/update/urn:li:share:123456"
              blogUrl:
                type: string
                format: uri
                description: Original blog URL
                example: "https://journey.thakurganeshsingh.com/blog/new-blog-post"
              title:
                type: string
                description: Blog title
                example: "My New Blog Post"

    AutoPublishStatusResponse:
      type: object
      properties:
        success:
          type: boolean
          description: Whether the status check was successful
          example: true
        publishedCount:
          type: integer
          description: Total number of blogs published to LinkedIn
          example: 15
        publishedBlogs:
          type: array
          description: List of published blog slugs
          items:
            type: string
          example: ["blog-post-1", "blog-post-2", "latest-update"]
        lastCheck:
          type: string
          format: date-time
          description: Timestamp of last status check
          example: "2024-01-15T10:30:00Z"

    NotificationRequest:
      type: object
      required:
        - type
        - title
        - url
      properties:
        type:
          type: string
          enum: ["blog", "project", "achievement"]
          description: Type of content being shared
          example: "blog"
        title:
          type: string
          description: Content title
          example: "Advanced React Patterns for 2024"
          maxLength: 200
        excerpt:
          type: string
          description: Brief description or excerpt
          example: "Explore the latest React patterns including Server Components..."
          maxLength: 500
        url:
          type: string
          format: uri
          description: URL to the full content
          example: "https://journey.thakurganeshsingh.com/blog/react-patterns-2024"
        coverImage:
          type: string
          format: uri
          description: Optional cover image URL
          example: "https://journey.thakurganeshsingh.com/images/blog/react-patterns.jpg"

    NotificationResponse:
      type: object
      properties:
        success:
          type: boolean
          description: Indicates if notifications were sent successfully
          example: true
        message:
          type: string
          description: Summary message
          example: "Notification sent to 150 subscribers"
        stats:
          type: object
          description: Delivery statistics
          properties:
            successful:
              type: integer
              description: Number of successful email deliveries
              example: 148
            failed:
              type: integer
              description: Number of failed email deliveries
              example: 2
            total:
              type: integer
              description: Total number of subscribers contacted
              example: 150

    ContactFormRequest:
      type: object
      required:
        - name
        - email
        - subject
        - message
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 100
          description: Full name of the person submitting the form
          example: "John Doe"
        email:
          type: string
          format: email
          description: Valid email address for response
          example: "john.doe@example.com"
        subject:
          type: string
          minLength: 1
          maxLength: 200
          description: Subject line for the message
          example: "Collaboration Opportunity"
        message:
          type: string
          minLength: 1
          maxLength: 1000
          description: Main message content
          example: "Hi Ganesh, I'd like to discuss a potential collaboration on a developer advocacy project."

    ContactFormResponse:
      type: object
      properties:
        success:
          type: boolean
          description: Indicates if the form was submitted successfully
          example: true
        message:
          type: string
          description: Confirmation message for the user
          example: "Thank you for your message. I will get back to you soon!"

    NavigationResponse:
      type: object
      properties:
        success:
          type: boolean
          description: Indicates if navigation was retrieved successfully
          example: true
        navigation:
          type: array
          description: Hierarchical navigation structure
          items:
            $ref: '#/components/schemas/NavigationItem'

    NavigationItem:
      type: object
      properties:
        title:
          type: string
          description: Display title for the navigation item
          example: "API Reference"
        href:
          type: string
          description: URL path for the navigation item
          example: "/docs/api"
        description:
          type: string
          description: Optional description of the page content
          example: "Complete API documentation and examples"
        items:
          type: array
          description: Child navigation items
          items:
            $ref: '#/components/schemas/NavigationItem'

    SiteInfo:
      type: object
      properties:
        name:
          type: string
          example: "Thakur Ganeshsingh"
        title:
          type: string
          example: "Developer Advocate & Solutions Architect"
        description:
          type: string
          example: "Dynamic technical leader with 10+ years of experience in software engineering, developer advocacy, and system architecture."
        url:
          type: string
          format: uri
          example: "https://journey.thakurganeshsingh.com"
        type:
          type: string
          example: "personal_portfolio"
        lastModified:
          type: string
          format: date-time
        personal:
          $ref: '#/components/schemas/PersonalInfo'
        professional:
          $ref: '#/components/schemas/ProfessionalInfo'
        technical:
          $ref: '#/components/schemas/TechnicalSkills'
        achievements:
          $ref: '#/components/schemas/Achievements'
        education:
          $ref: '#/components/schemas/Education'
        pages:
          type: array
          items:
            $ref: '#/components/schemas/PageInfo'
        social:
          $ref: '#/components/schemas/SocialLinks'
        ai_metadata:
          $ref: '#/components/schemas/AIMetadata'

    PersonalInfo:
      type: object
      properties:
        name:
          type: string
          example: "Thakur Ganeshsingh"
        roles:
          type: array
          items:
            type: string
          example: ["Developer Advocate", "Solutions Architect", "Engineering Manager"]
        location:
          type: string
          example: "Bangalore, India"
        email:
          type: string
          format: email
          example: "thakurg785@thakurganeshsingh.com"
        currentCompany:
          type: string
          example: "Freshworks"
        experience:
          type: string
          example: "10+ years"
        specialties:
          type: array
          items:
            type: string
          example: ["Developer Relations", "System Architecture", "Full Stack Development"]

    ProfessionalInfo:
      type: object
      properties:
        summary:
          type: string
          example: "Dynamic technical leader with 10+ years of experience driving successful software engineering initiatives."
        expertise:
          type: array
          items:
            type: string
          example: ["Software Engineering", "Developer Advocacy", "System Architecture"]
        currentRole:
          $ref: '#/components/schemas/CurrentRole'

    CurrentRole:
      type: object
      properties:
        title:
          type: string
          example: "Developer Advocate"
        company:
          type: string
          example: "Freshworks"
        description:
          type: string
          example: "Helping developers build better apps with powerful tooling, clear docs, and community-driven enablement."

    TechnicalSkills:
      type: object
      properties:
        languages:
          type: array
          items:
            type: string
          example: ["JavaScript", "TypeScript", "Python", "Java", "Node.js"]
        frontend:
          type: array
          items:
            type: string
          example: ["React", "Next.js", "Vue.js", "Angular", "Tailwind CSS"]
        backend:
          type: array
          items:
            type: string
          example: ["Node.js", "Express", "Spring Boot", "Django", "RESTful APIs"]
        cloud:
          type: array
          items:
            type: string
          example: ["AWS", "Google Cloud", "Azure", "Docker", "Kubernetes"]
        databases:
          type: array
          items:
            type: string
          example: ["PostgreSQL", "MongoDB", "Redis", "MySQL", "DynamoDB"]
        tools:
          type: array
          items:
            type: string
          example: ["Git", "Jenkins", "Docker", "Kubernetes", "Grafana"]

    Achievements:
      type: object
      properties:
        projects:
          type: string
          example: "23+ projects worth $32M"
        experience:
          type: string
          example: "10+ years in tech industry"
        companies:
          type: array
          items:
            type: string
          example: ["Freshworks", "Oracle", "Nissan", "Bazaarvoice"]
        certifications:
          type: array
          items:
            type: string
          example: ["AWS Solutions Architect", "Google Cloud Professional", "Oracle Certified"]
        recognition:
          type: string
          example: "Multiple industry awards and certifications"

    Education:
      type: object
      properties:
        degree:
          type: string
          example: "Master of Engineering"
        field:
          type: string
          example: "Computer Engineering"
        institution:
          type: string
          example: "University Visvesvaraya College of Engineering (UVCE)"
        location:
          type: string
          example: "Bangalore, India"

    PageInfo:
      type: object
      properties:
        path:
          type: string
          example: "/projects"
        title:
          type: string
          example: "Projects"
        description:
          type: string
          example: "Portfolio of technical projects and contributions"

    SocialLinks:
      type: object
      properties:
        linkedin:
          type: string
          format: uri
          example: "https://linkedin.com/in/thakur-ganeshsingh"
        github:
          type: string
          format: uri
          example: "https://github.com/ganeshsingh"
        twitter:
          type: string
          format: uri
          example: "https://twitter.com/ganeshsinghtha1"
        email:
          type: string
          format: email
          example: "thakurg785@thakurganeshsingh.com"

    AIMetadata:
      type: object
      properties:
        crawlable:
          type: boolean
          example: true
        content_type:
          type: string
          example: "professional_portfolio"
        primary_topics:
          type: array
          items:
            type: string
          example: ["software engineering", "developer advocacy", "system architecture"]
        suitable_for:
          type: array
          items:
            type: string
          example: ["career inquiries", "technical consultations", "speaking engagements"]
        last_updated:
          type: string
          format: date-time
        content_freshness:
          type: string
          example: "regularly_updated"

    SecurityHealthResponse:
      type: object
      properties:
        status:
          type: string
          enum: ["healthy", "degraded", "unhealthy"]
          example: "healthy"
        timestamp:
          type: string
          format: date-time
          example: "2024-01-15T10:30:00.000Z"
        security:
          $ref: '#/components/schemas/SecurityFeatures'
        environment:
          type: string
          example: "production"
        version:
          type: string
          example: "1.0.0"

    SecurityFeatures:
      type: object
      properties:
        headers_enabled:
          type: boolean
          example: true
        rate_limiting:
          type: boolean
          example: true
        input_validation:
          type: boolean
          example: true
        csrf_protection:
          type: boolean
          example: true
        xss_protection:
          type: boolean
          example: true
        content_security_policy:
          type: boolean
          example: true

    LLMContextResponse:
      type: object
      description: Structured information optimized for LLM consumption
      properties:
        context:
          type: object
          description: Professional context information
        skills:
          type: object
          description: Technical skills and expertise
        experience:
          type: object
          description: Career experience and achievements
        current_role:
          type: object
          description: Current position and responsibilities

    ErrorResponse:
      type: object
      properties:
        error:
          type: string
          description: Error message describing what went wrong
          example: "Missing required fields"
        success:
          type: boolean
          description: Always false for error responses
          example: false

  securitySchemes:
    OriginValidation:
      type: apiKey
      in: header
      name: Origin
      description: |
        CSRF protection through origin validation. Requests must come from allowed origins.
        
        The server validates the Origin header to prevent cross-site request forgery attacks.
        
    UserAgentValidation:
      type: apiKey
      in: header
      name: User-Agent
      description: |
        User agent validation to prevent malicious access.
        
        The server validates the User-Agent header to block known malicious bots and scrapers
        while allowing legitimate access from browsers and approved automated systems.
        
    InternalAPIKey:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: |
        Internal API key for authenticated endpoints like LinkedIn publishing and notifications.
        
        **Required for:**
        - `/linkedin-publish` - Auto-publish blog posts to LinkedIn
        - `/notify-subscribers` - Send email notifications to subscribers
        
        **How to get your API key:**
        1. Generate a secure 32-character key: `openssl rand -hex 32`
        2. Set as `INTERNAL_API_KEY` in your environment variables
        3. Include in requests as `Authorization: Bearer YOUR_API_KEY`

    AutoPublishSecret:
      type: http
      scheme: bearer
      bearerFormat: Secret Token
      description: |
        Auto-publish secret for triggering automated blog publishing to LinkedIn.
        
        **Required for:**
        - `/blog-auto-publish` - Automatically publish blog posts to LinkedIn
        
        **Typical Usage:**
        - Called by GitHub Actions after successful deployment
        - Used by CI/CD pipelines for automated content distribution
        - Can be called manually from admin dashboard
        
        **How to configure:**
        1. Generate a secure random string: `openssl rand -base64 24`
        2. Set as `AUTO_PUBLISH_SECRET` in your environment variables
        3. Add the same value to GitHub repository secrets
        4. Include in requests as `Authorization: Bearer YOUR_SECRET`
        
        **Security Notes:**
        - This should be different from your INTERNAL_API_KEY
        - Keep this secret secure and rotate it regularly
        - Only share with trusted CI/CD systems
        
        **Security Features:**
        - Rate limiting per API key
        - Request origin validation
        - Input sanitization and validation
        - Comprehensive audit logging
        
        **Testing:**
        - For localhost testing, use your development API key
        - Never commit API keys to version control
        - Rotate keys regularly for security

    ResendAPIKey:
      type: http
      scheme: bearer  
      bearerFormat: API Key
      description: |
        Resend API key for email functionality testing.
        
        **For Testing Newsletter & Notifications:**
        This allows you to test email functionality with your own Resend credentials.
        
        **How to get your Resend API key:**
        1. Sign up at [resend.com](https://resend.com)
        2. Verify your domain
        3. Create API key with "Sending access"
        4. Use format: `re_your_api_key_here`
        
        **Setup Requirements:**
        - Domain verified in Resend dashboard
        - Sender email must use verified domain
        - Free tier: 100 emails/day, 3,000/month
        
        **Environment Variables:**
        ```
        RESEND_API_KEY="re_your_api_key_here"
        RESEND_SENDER_EMAIL="noreply@your-domain.com"
        RESEND_SENDER_NAME="Your Name"
        ```

security:
  - OriginValidation: []
  - UserAgentValidation: []