ShopFloorAI

An AI-powered service for optimizing work assignments in ShopFloorOS.

API Endpoint
This service exposes a single, secure API endpoint to get the next best work assignment.

Make a POST request to the following endpoint with your `shopId` to receive an optimal assignment suggestion. Once this app is deployed, the URL below will update with your public address.

curl -X POST "https://t-2434131538---studio-2zfq5dnrya-uc.a.run.app/api/v1/suggest-action" \
-H "Authorization: Bearer ${MIDDLE_MANAGER_API_SECRET}" \
-H "Content-Type: application/json" \
-d '{"shopId": "shop-123"}'
bash

Note: Authentication is handled via a Bearer token. Ensure the `MIDDLE_MANAGER_API_SECRET` environment variable is set on your server and used in the `Authorization` header. You can find the secret in your `.env` file.

Data Schema Context
The AI uses the following data schema from `docs/backend.json` to understand the structure of Work Orders and Employees.
{
  "entities": {
    "WorkOrder": {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "title": "WorkOrder",
      "type": "object",
      "description": "Represents a work order in the ShopFloorOS system.",
      "properties": {
        "id": {
          "type": "string",
          "description": "Unique identifier for the work order."
        },
        "shopId": {
          "type": "string",
          "description": "Reference to Shop. (Relationship: Shop 1:N WorkOrder)"
        },
        "description": {
          "type": "string",
          "description": "Description of the work order."
        },
        "status": {
          "type": "string",
          "description": "Current status of the work order (e.g., Pending, In Progress, Completed)."
        },
        "department": {
          "type": "string",
          "description": "Department this work order belongs to."
        },
        "createdAt": {
          "type": "string",
          "description": "Timestamp of when the work order was created.",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "shopId",
        "description",
        "status",
        "department",
        "createdAt"
      ]
    },
    "Employee": {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "title": "Employee",
      "type": "object",
      "description": "Represents an employee in the ShopFloorOS system.",
      "properties": {
        "id": {
          "type": "string",
          "description": "Unique identifier for the employee."
        },
        "shopId": {
          "type": "string",
          "description": "Reference to Shop. (Relationship: Shop 1:N Employee)"
        },
        "name": {
          "type": "string",
          "description": "Name of the employee."
        },
        "department": {
          "type": "string",
          "description": "Department the employee belongs to."
        },
        "efficiency": {
          "type": "number",
          "description": "Employee's overall efficiency score."
        }
      },
      "required": [
        "id",
        "shopId",
        "name",
        "department",
        "efficiency"
      ]
    },
    "Shop": {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "title": "Shop",
      "type": "object",
      "description": "Represents a shop in the ShopFloorOS system.",
      "properties": {
        "id": {
          "type": "string",
          "description": "Unique identifier for the shop."
        },
        "name": {
          "type": "string",
          "description": "Name of the shop."
        },
        "location": {
          "type": "string",
          "description": "Location of the shop."
        }
      },
      "required": [
        "id",
        "name",
        "location"
      ]
    },
    "PerformanceData": {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "title": "PerformanceData",
      "type": "object",
      "description": "Represents an employee's performance data for a completed work order.",
      "properties": {
        "id": {
          "type": "string",
          "description": "Unique identifier for the performance data entry."
        },
        "employeeId": {
          "type": "string",
          "description": "Reference to Employee. (Relationship: Employee 1:N PerformanceData)"
        },
        "workOrderId": {
          "type": "string",
          "description": "Reference to WorkOrder. (Relationship: WorkOrder 1:N PerformanceData)"
        },
        "cycleTime": {
          "type": "number",
          "description": "Cycle time for the work order."
        },
        "date": {
          "type": "string",
          "description": "Date when the work order was completed.",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "employeeId",
        "workOrderId",
        "cycleTime",
        "date"
      ]
    }
  },
  "auth": {
    "providers": [
      "password",
      "anonymous"
    ]
  },
  "firestore": {
    "structure": [
      {
        "path": "shops/{shopId}",
        "definition": {
          "entityName": "Shop",
          "schema": {
            "$ref": "#/backend/entities/Shop"
          },
          "description": "Stores shop data. Used by the AI to fetch shop details.",
          "params": [
            {
              "name": "shopId",
              "description": "The unique identifier of the shop."
            }
          ]
        }
      },
      {
        "path": "shops/{shopId}/employees/{employeeId}",
        "definition": {
          "entityName": "Employee",
          "schema": {
            "$ref": "#/backend/entities/Employee"
          },
          "description": "Stores employee data within a specific shop. The AI uses this to analyze employee performance and efficiency.  Path follows pattern `/shops/{shopId}/employees/{employeeId}`.",
          "params": [
            {
              "name": "shopId",
              "description": "The unique identifier of the shop."
            },
            {
              "name": "employeeId",
              "description": "The unique identifier of the employee."
            }
          ]
        }
      },
      {
        "path": "shops/{shopId}/workOrders/{workOrderId}",
        "definition": {
          "entityName": "WorkOrder",
          "schema": {
            "$ref": "#/backend/entities/WorkOrder"
          },
          "description": "Stores work order data within a specific shop. The AI uses this to fetch pending work orders. Path follows pattern `/shops/{shopId}/workOrders/{workOrderId}`.",
          "params": [
            {
              "name": "shopId",
              "description": "The unique identifier of the shop."
            },
            {
              "name": "workOrderId",
              "description": "The unique identifier of the work order."
            }
          ]
        }
      },
      {
        "path": "shops/{shopId}/employees/{employeeId}/performanceData/{performanceDataId}",
        "definition": {
          "entityName": "PerformanceData",
          "schema": {
            "$ref": "#/backend/entities/PerformanceData"
          },
          "description": "Stores performance data for employees on specific work orders within a given shop.  This is used by the AI to analyze historical performance data. Path follows pattern `/shops/{shopId}/employees/{employeeId}/performanceData/{performanceDataId}`.",
          "params": [
            {
              "name": "shopId",
              "description": "The unique identifier of the shop."
            },
            {
              "name": "employeeId",
              "description": "The unique identifier of the employee."
            },
            {
              "name": "performanceDataId",
              "description": "The unique identifier of the performance data entry."
            }
          ]
        }
      }
    ],
    "reasoning": "Given the Middle Manager AI application's read-only access to the ShopFloorOS Firestore database, the primary focus is on structuring the data access patterns for the AI to efficiently determine optimal work order assignments.  The structure mirrors the existing ShopFloorOS database for data consistency and utilizes structural segregation to optimize queries for pending work orders and employee data. Since the AI only reads the data, denormalization for authorization independence is not applicable here as there are no security rules needed for writes. The structure supports the required QAPs by directly reflecting the organization of the existing ShopFloorOS database, enabling efficient queries for work orders, employees, and historical performance data. The AI needs to be able to fetch `Shop`, `Employee`, `WorkOrder`, and `PerformanceData` documents.  The structure below mirrors the parent application's structure to ensure that these documents can be located by the AI."
  }
}
json