personal-lifecycle-tracker / openapi.yaml
openapi.yaml
Raw
openapi: 3.0.3
info:
  title: Personal Lifecycle Tracker API
  description: >
    Production REST API for Personal Lifecycle Tracker.
    Manages Renewals, Maintenance, and Warranties for independent users and shared groups,
    including action summaries and scheduled daily morning email digests.    
  version: 1.0.0
servers:
  - url: http://localhost:8003
    description: Local Container Runtime
  - url: http://localhost:8000
    description: Alternative Container Port

paths:
  /health:
    get:
      summary: Liveness and readiness healthcheck
      description: Returns health status of service and database connectivity.
      responses:
        '200':
          description: Service is healthy
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HealthStatus'

  /api/v1/auth/signup:
    post:
      summary: Register a new user
      description: Register a new independent user account using email, password, and display name.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SignupRequest'
      responses:
        '201':
          description: User registered successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
        '400':
          description: Invalid request or email already exists
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/auth/login:
    post:
      summary: Log in with email and password
      description: Authenticate an existing user and obtain a JWT bearer token.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LoginRequest'
      responses:
        '200':
          description: Authentication successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
        '401':
          description: Invalid credentials
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/auth/me:
    get:
      summary: Retrieve current authenticated user
      description: Returns the user record corresponding to the provided JWT bearer token.
      security:
        - BearerAuth: []
      responses:
        '200':
          description: Authenticated user details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/auth/logout:
    post:
      summary: Log out current user
      description: Invalidates or acknowledges client session termination.
      responses:
        '200':
          description: Logged out successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'

  /api/v1/users:
    get:
      summary: List all registered users (demo / dev discovery)
      description: Returns all users for testing multi-user switching and group invitations.
      responses:
        '200':
          description: List of users
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'

  /api/v1/users/{userId}:
    delete:
      summary: Delete user account and cascade delete owned items and groups
      description: Permanently deletes a user account, their personal items, and owned groups.
      security:
        - BearerAuth: []
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: string
      responses:
        '204':
          description: User account deleted successfully
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: User not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/items:
    get:
      summary: List lifecycle items accessible to user
      description: >
        Returns personal items owned by the current user plus shared group items
        for groups in which the user is a member.        
      security:
        - BearerAuth: []
      parameters:
        - name: groupId
          in: query
          required: false
          schema:
            type: string
            nullable: true
          description: Filter by groupId ('null' for personal items only)
        - name: type
          in: query
          required: false
          schema:
            $ref: '#/components/schemas/LifecycleType'
        - name: searchQuery
          in: query
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Array of lifecycle items
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/LifecycleItem'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      summary: Create a new lifecycle item
      description: Creates a new lifecycle item under personal ownership or within a shared group.
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateItemDTO'
      responses:
        '201':
          description: Item created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LifecycleItem'
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/items/{id}:
    get:
      summary: Get lifecycle item by ID
      description: Fetches a single lifecycle item accessible to the current user.
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Lifecycle item
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LifecycleItem'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Item not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    patch:
      summary: Update a lifecycle item
      description: Updates editable common fields of a personal or shared group item.
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateItemDTO'
      responses:
        '200':
          description: Updated item
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LifecycleItem'
        '400':
          description: Validation or permission error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Item not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      summary: Permanently delete a lifecycle item
      description: Deletes an item permanently (owner or group member).
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '204':
          description: Item deleted successfully
        '400':
          description: Permission error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Item not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/items/{id}/complete:
    post:
      summary: Toggle or mark item completion
      description: Toggles item status between 'active' and 'completed'. Retained in main list.
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Item with updated completion status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LifecycleItem'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Item not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/groups:
    get:
      summary: List groups for current user
      description: Returns all groups where the current user is an owner or member.
      security:
        - BearerAuth: []
      responses:
        '200':
          description: Array of groups
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Group'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      summary: Create a new shared group
      description: Creates a shared group with the current user as owner.
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateGroupRequest'
      responses:
        '201':
          description: Group created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Group'
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/groups/{id}:
    get:
      summary: Get group by ID
      description: Fetches details for a specific group accessible to the user.
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Group details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Group'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Group not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      summary: Delete group and cascade delete group items
      description: Deletes a group and all its associated items. Only permitted by group owner.
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '204':
          description: Group deleted successfully
        '400':
          description: Permission denied or operation failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Group not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/groups/{groupId}/members:
    post:
      summary: Invite or add member to group
      description: Invites/adds a member by email address to the shared group.
      security:
        - BearerAuth: []
      parameters:
        - name: groupId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddMemberRequest'
      responses:
        '200':
          description: Member added successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Group'
        '400':
          description: Invalid request or permission denied
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Group not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/groups/{groupId}/members/{memberEmail}:
    delete:
      summary: Remove member from group
      description: Removes a member from a group. Group items remain with the group.
      security:
        - BearerAuth: []
      parameters:
        - name: groupId
          in: path
          required: true
          schema:
            type: string
        - name: memberEmail
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Member removed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Group'
        '400':
          description: Permission denied or invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Group not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/groups/{groupId}/leave:
    post:
      summary: Leave a group
      description: Allows a non-owner member to leave a shared group. Items remain with the group.
      security:
        - BearerAuth: []
      parameters:
        - name: groupId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Successfully left group
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
        '400':
          description: Cannot leave as owner or invalid group
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Group not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/reminders/summary:
    get:
      summary: Get active reminders summary (overdue, upcoming, total count)
      description: Aggregates overdue and upcoming active items for the authenticated user.
      security:
        - BearerAuth: []
      responses:
        '200':
          description: Summary of active alerts
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RemindersSummary'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/reminders/digest/config:
    get:
      summary: Get daily digest configuration
      description: Returns configuration for daily email digest (deliveryTime, timeZone, enabled).
      responses:
        '200':
          description: Current digest configuration
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DailyDigestConfig'
    patch:
      summary: Update daily digest configuration
      description: Updates delivery time or timezone settings. Reminder channels remain enabled.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateDigestConfigRequest'
      responses:
        '200':
          description: Updated digest config
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DailyDigestConfig'
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/reminders/digest/generate:
    post:
      summary: Generate and send or preview daily digest email
      description: Generates the daily digest email payload containing upcoming and overdue items.
      security:
        - BearerAuth: []
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GenerateDigestRequest'
      responses:
        '200':
          description: Generated digest email payload
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DailyDigestEmail'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/reminders/digest/history:
    get:
      summary: List historical sent digest emails
      description: Returns recent sent digest emails.
      responses:
        '200':
          description: Array of sent digests
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/DailyDigestEmail'

  /api/v1/dev/seed:
    post:
      summary: Reset and seed demo data
      description: Resets data store to initial seed users, groups, and items.
      responses:
        '200':
          description: Seed complete
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

  schemas:
    HealthStatus:
      type: object
      required:
        - status
        - database
        - version
      properties:
        status:
          type: string
          example: healthy
        database:
          type: string
          example: connected
        version:
          type: string
          example: 1.0.0

    LifecycleType:
      type: string
      enum:
        - renewal
        - maintenance
        - warranty

    ItemStatus:
      type: string
      enum:
        - active
        - completed

    ItemUrgency:
      type: string
      enum:
        - overdue
        - upcoming
        - normal
        - no_date
        - completed

    DigestDeliveryTime:
      type: string
      enum:
        - '06:00'
        - '08:00'
        - '09:00'
        - '12:00'
      example: '08:00'

    User:
      type: object
      required:
        - id
        - email
        - name
        - createdAt
      properties:
        id:
          type: string
          example: user_alex
        email:
          type: string
          format: email
          example: alex@example.com
        name:
          type: string
          example: Alex Taylor
        createdAt:
          type: string
          format: date-time
          example: '2026-01-10T08:00:00Z'

    AuthResponse:
      type: object
      required:
        - user
        - token
      properties:
        user:
          $ref: '#/components/schemas/User'
        token:
          type: string
          example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

    SignupRequest:
      type: object
      required:
        - email
        - password
        - name
      properties:
        email:
          type: string
          format: email
          example: newuser@example.com
        password:
          type: string
          minLength: 6
          example: secretPass123
        name:
          type: string
          example: New User

    LoginRequest:
      type: object
      required:
        - email
        - password
      properties:
        email:
          type: string
          format: email
          example: alex@example.com
        password:
          type: string
          example: password123

    LifecycleItem:
      type: object
      required:
        - id
        - name
        - lifecycleType
        - status
        - ownerId
        - ownerEmail
        - createdAt
        - updatedAt
      properties:
        id:
          type: string
          example: item_1
        name:
          type: string
          example: Vehicle Auto Insurance Policy
        lifecycleType:
          $ref: '#/components/schemas/LifecycleType'
        dueDate:
          type: string
          format: date
          nullable: true
          example: '2026-11-15'
        status:
          $ref: '#/components/schemas/ItemStatus'
        ownerId:
          type: string
          example: user_alex
        ownerEmail:
          type: string
          format: email
          example: alex@example.com
        groupId:
          type: string
          nullable: true
          example: group_vehicles
        groupName:
          type: string
          nullable: true
          example: Shared Vehicle Maintenance
        createdAt:
          type: string
          format: date-time
          example: '2026-08-01T08:00:00Z'
        updatedAt:
          type: string
          format: date-time
          example: '2026-08-01T08:00:00Z'

    CreateItemDTO:
      type: object
      required:
        - name
        - lifecycleType
      properties:
        name:
          type: string
          example: Vehicle Oil & Filter Change
        lifecycleType:
          $ref: '#/components/schemas/LifecycleType'
        dueDate:
          type: string
          format: date
          nullable: true
          example: '2026-10-25'
        status:
          $ref: '#/components/schemas/ItemStatus'
          default: active
        groupId:
          type: string
          nullable: true
          example: group_vehicles

    UpdateItemDTO:
      type: object
      properties:
        name:
          type: string
          example: Updated Policy Name
        lifecycleType:
          $ref: '#/components/schemas/LifecycleType'
        dueDate:
          type: string
          format: date
          nullable: true
          example: '2026-12-01'
        status:
          $ref: '#/components/schemas/ItemStatus'
        groupId:
          type: string
          nullable: true
          example: null

    Group:
      type: object
      required:
        - id
        - name
        - ownerId
        - ownerEmail
        - memberEmails
        - createdAt
      properties:
        id:
          type: string
          example: group_home
        name:
          type: string
          example: Oakridge Family & Home
        ownerId:
          type: string
          example: user_alex
        ownerEmail:
          type: string
          format: email
          example: alex@example.com
        memberEmails:
          type: array
          items:
            type: string
            format: email
          example:
            - alex@example.com
            - sarah@example.com
        createdAt:
          type: string
          format: date-time
          example: '2026-02-15T10:00:00Z'

    CreateGroupRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          example: Family & Home

    AddMemberRequest:
      type: object
      required:
        - email
      properties:
        email:
          type: string
          format: email
          example: member@example.com

    DailyDigestConfig:
      type: object
      required:
        - timeZone
        - deliveryTime
        - enabled
      properties:
        timeZone:
          type: string
          example: America/New_York
        deliveryTime:
          $ref: '#/components/schemas/DigestDeliveryTime'
        enabled:
          type: boolean
          example: true

    UpdateDigestConfigRequest:
      type: object
      properties:
        timeZone:
          type: string
          example: America/New_York
        deliveryTime:
          $ref: '#/components/schemas/DigestDeliveryTime'
        enabled:
          type: boolean
          example: true

    DailyDigestEmail:
      type: object
      required:
        - id
        - recipientEmail
        - recipientName
        - generatedAt
        - deliveryTime
        - timeZone
        - subject
        - overdueCount
        - upcomingCount
        - overdueItems
        - upcomingItems
        - htmlContent
        - textContent
      properties:
        id:
          type: string
          example: digest_1728518400000
        recipientEmail:
          type: string
          format: email
          example: alex@example.com
        recipientName:
          type: string
          example: Alex Taylor
        generatedAt:
          type: string
          format: date-time
          example: '2026-10-09T08:00:00Z'
        deliveryTime:
          $ref: '#/components/schemas/DigestDeliveryTime'
        timeZone:
          type: string
          example: America/New_York
        subject:
          type: string
          example: 'Daily Lifecycle Digest: 2 Overdue, 3 Upcoming Actions'
        overdueCount:
          type: integer
          example: 2
        upcomingCount:
          type: integer
          example: 3
        overdueItems:
          type: array
          items:
            $ref: '#/components/schemas/LifecycleItem'
        upcomingItems:
          type: array
          items:
            $ref: '#/components/schemas/LifecycleItem'
        htmlContent:
          type: string
        textContent:
          type: string

    GenerateDigestRequest:
      type: object
      properties:
        recipientEmail:
          type: string
          format: email
          nullable: true
          example: alex@example.com

    RemindersSummary:
      type: object
      required:
        - overdue
        - upcoming
        - totalActiveReminders
      properties:
        overdue:
          type: array
          items:
            $ref: '#/components/schemas/LifecycleItem'
        upcoming:
          type: array
          items:
            $ref: '#/components/schemas/LifecycleItem'
        totalActiveReminders:
          type: integer
          example: 5

    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          example: Resource not found

    MessageResponse:
      type: object
      required:
        - message
      properties:
        message:
          type: string
          example: Operation completed successfully