[
  {
    "FeatureName":"Base API App Setup & App Security Layer",
    "Details":[
      { "SubFeatureName":"API Home",
        "ApiRoute":"GET - /en/v1",
        "Description":[
          "accept get request to api home",
          "return json response, server session cookie & csrf token cookie"],
        "Requirements": [
          "[OK]:AppMaster w/ all needed middleware, DB, Logger",
          "[OK]:whitelisted origin",
          "[OK]:valid API credentials",
          "[OK]:valid ip data"],
        "ErrorTestCases":[
          "[OK]:[403]:no origin (unrecognized)",
          "[OK]:[403]:bad origin (not whitelisted)",
          "[OK]:[401]:no API client credentials",
          "[OK]:[401]:invalid API client credentials",
          "[DEV]:[403]:blacklisted users/ips"],
        "SuccessTestCases":[
          "[OK]:Middleware - Disable 'X-Powered_By' header",
          "[OK]:Middleware (AppMaster.Middleware.Compression) - compress response",
          "[OK]:Middleware (AppMaster.Middleware.Morgan) - Format request log msg and trigger logger",
          "[OK]:Middleware (AppMaster.Middleware.CORS) - CORS & origin check",
          "[OK]:Middleware (AppMaster.Middleware.custom['apiCreds']) - validate API credentials",
          "[OK]:Middleware (AppMaster.Middleware.CookieParser) - Parse cookies",
          "[OK]:Middleware (AppMaster.Middleware.BodyParser) - Parse body",
          "[OK]:Middleware (AppMaster.Middleware.Session) - retrieve server sesssion",
          "[OK]:Middleware (AppMaster.Middleware.custom['ipData']) - validate ip data",
          "[DEV]:Middleware (AppMaster.Middleware.custom['sessVars']) - update session vars and meter server access",
          "[OK]:Middleware (AppMaster.Middleware.CSRF) - validate CSRF token & passphrase",
          "[OK]:Middleware (AppMaster.Middleware.PageNotFound) - handle resource not found",
          "[OK]:Middleware (AppMaster.Middleware.FinalHandler) - return well-formatted error",
          "[OK]:[200]:return {api:'ready'} along with csrf token & session cookies",
          "[OK]:Middleware (AppMaster.Logger) - Log/write to file request log msg - access, warn, error (499 < status)",
          "[DEV]:reroute to 'https' with valid server SSL certificate"]},
      { "SubFeatureName":"Resource Found/Not Found",
        "ApiRoute":"GET - /en/v1/test & GET - /en/v1/test1",
        "Description":[
          "accept get request to api home",
          "return json response if url exists",
          "return 404 error if url does not exist"],
        "Requirements": [
          "[OK]:whitelisted origin",
          "[OK]:valid API credentials",
          "[OK]:valid server session cookie"],
        "ErrorTestCases":["[OK]:[401]:missing session cookie"],
        "SuccessTestCases":[
          "[OK]:[200]:return {test:true} @ '/en/v1/test'",
          "[OK]:[404]:return 'resource not found' error @ '/en/v1/test1'"]},
      { "SubFeatureName":"Post Data To API",
        "ApiRoute":"POST - /en/v1/test",
        "Description":[
          "accept post request with test data in req body",
          "perform server operation on test data",
          "return json response after server operation"],
        "Requirements":[
          "[OK]:whitelisted origin",
          "[OK]:valid API credentials",
          "[OK]:valid server session cookie",
          "[OK]:valid csrf token header & csrf passphrase within session cookie"],
        "ErrorTestCases":[
          "[OK]:[401]:request cookie - missing session",
          "[OK]:[401]:request cookie - missing csrf passphrase from session",
          "[OK]:[403]:request header - missing csrf token",
          "[OK]:[403]:request header - invalid csrf token format",
          "[OK]:[403]:request header - csrf token mismatch",
          "[OK]:[422]:request body - missing test data",
          "[OK]:[422]:request body - invalid test data format"],
        "SuccessTestCases":[
          "[DEV]:sanitize request body,query,params",
          "[OK]:perform operation on test data",
          "[OK]:[200]:return confirmation of operation"]}
    ]
  },
  {
    "FeatureName":"PPT User Authentication & Acct Mgmt",
    "Details":[
      { "SubFeatureName":"Register New User",
        "ApiRoute":"POST - /en/v1/auth/register",
        "Description":[
          "accept post request with user email & role in request body",
          "create new user record on DB using email only",
          "trigger Notifier API to send email with verification code to the email address provided",
          "generate auth request token with email verification privilege",
          "return user acct details & token formatted for app consumption"],
        "Requirements": [
          "[OK]:Request must pass Base API security",
          "[OK]:Request body must have vaild 'email' field"],
        "ErrorTestCases":[
          "[OK]:[422]:request body missing email, role",
          "[OK]:[422]:invalid email format",
          "[OK]:[422]:email address already exists within DB"],
        "SuccessTestCases":[
          "[OK]:create & save new user record on DB",
          "[OK]:generate email verification code and save to user",
          "[OK]:generate auth request token with email, role & okto = 'verify'",
          "[OK]:[201]:return user details & token",
          "[DEV]:send verification email via PPT Notifier API"]},
      { "SubFeatureName":"Verify Registered User",
        "ApiRoute":"POST - /en/v1/auth/verify",
        "Description":[
          "accept post request with verification code in request body",
          "fetch user record from DB and validate verification code",
          "update with user acct status",
          "return auth request token with complete registration privilege"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request body must have vaild 'code' field"],
        "ErrorTestCases":[
          "[OK]:[422]:request header - missing auth request token [422]",
          "[OK]:[422]:request header - invalid auth request token format [422]",
          "[OK]:[401]:auth request token header contains username (as email) & okto = 'verify' [401]",
          "[OK]:[422]:request body - missing verification code [422]",
          "[OK]:[422]:request body - invalid verification code format [422]",
          "[OK]:[422]:user not found via username (as email) from DB [422]",
          "[OK]:[422]:verification code does not match DB [422]"],
        "SuccessTestCases":[
          "[OK]:save updates to user record on DB",
          "[OK]:[200]:return auth request token with email, role, okto = 'complete-reg'"]},
      { "SubFeatureName":"Complete User Registration",
        "ApiRoute":"POST - /en/v1/auth/update",
        "Description":[
          "accept post request with user info (name {first,last}, pin, username, etc) in request body",
          "update user record in DB with user info",
          "return auth request token with login privilege"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request body must have vaild 'pin','name','username' fields"],
        "ErrorTestCases":[
          "[OK]:[422]:request header - missing auth request token",
          "[OK]:[422]:request header - invalid auth request token format",
          "[OK]:[401]:auth request token header contains username,role & okto = 'complete-reg'",
          "[OK]:[422]:request body - missing name, pin or username",
          "[OK]:[422]:request body - invalid pin format (4 digit as string)",
          "[OK]:[422]:user not found via username from DB"],
        "SuccessTestCases":[
          "[OK]:save updates to user record on DB",
          "[OK]:[200]:return auth request token, okto = 'login'",
          "[DEV]:send new user 'welcome' email via PPT Notifier API"]},
      { "SubFeatureName":"Set User",
        "ApiRoute":"POST - /en/v1/auth/set",
        "Description":[
          "accept post request with email/username in request body]",
          "fetch user acct in DB",
          "return auth request token with login privilege"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request body must have vaild 'username' field"],
        "ErrorTestCases":[
          "[OK]:[422]:request body missing username",
          "[OK]:[422]:invalid username format",
          "[OK]:[404]:user does not exists within DB"],
        "SuccessTestCases":["[OK]:[200]:return auth request token, okto = 'login'"]},
      { "SubFeatureName":"Login User",
        "ApiRoute":"POST - /en/v1/auth/login",
        "Description":[
          "accept post request with pin in request body",
          "fetch user record from DB and validate pin",
          "update user record in DB",
          "return auth request token with data api privilege"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request body must have vaild 'pin' field"],
        "ErrorTestCases":[
          "[OK]:[422]:request header - missing auth request token",
          "[OK]:[422]:request header - invalid auth request token format",
          "[OK]:[401]:auth request token header contains username & okto = 'login'",
          "[OK]:[422]:request body - missing pin",
          "[OK]:[422]:request body - invalid pin format",
          "[OK]:[422]:user not found via username from DB",
          "[OK]:[422]:pin does not match DB [422]"],
        "SuccessTestCases":["[OK]:[200]:return auth token, okto = 'use-data'"]},
      { "SubFeatureName":"Logout User",
        "ApiRoute":"DELETE - /en/v1/auth/login",
        "Description":[
          "accept del request with id as param",
          "fetch, update & save user record",
          "return logout confirmation"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[422]:request header - missing auth request token",
          "[OK]:[422]:request header - invalid auth request token format",
          "[OK]:[401]:auth request token header contains username & okto = 'use-data'",
          "[OK]:[404]:user not found via username from DB"],
        "SuccessTestCases":["[OK]:[201]:return logout confirmation'"]},
      { "SubFeatureName":"Forgot Pin",
        "ApiRoute":"GET - /en/v1/auth/login?",
        "Description":[
          "accept get request with usernme in req query",
          "fetch user from DB and generate reset token and link",
          "trigger Notifier API to send email with reset link to the email address provided",
          "update and save user on DB",
          "return pin reset email sent confirmation formatted for app consumption"],
        "Requirements":["[OK]:Request must pass Base API security"],
        "ErrorTestCases":[
          "[OK]:[422]:invalid username query",
          "[OK]:[404]:user not found from DB"],
        "SuccessTestCases":[
          "[OK]:fetch user record on DB",
          "[OK]:generate pin reset token & link and save to user",
          "[DEV]:send pin reset email via PPT Notifier API",
          "[OK]:[201]:return pin reset email confirmation"]},
      { "SubFeatureName":"Reset Pin",
        "ApiRoute":"PUT - /en/v1/auth/login?resetTkn=",
        "Description":[
          "accept put request with new pin in req body & reset token in req query",
          "fetch user record from DB and validate reset token",
          "update and save user",
          "return auth request token with login privilege"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request body must have vaild 'code' field"],
        "ErrorTestCases":[
          "[OK]:[422]:request header - missing auth request token [422]",
          "[OK]:[422]:request header - invalid auth request token format [422]",
          "[OK]:[401]:auth request token header contains username & okto = 'reset' [401]",
          "[OK]:[422]:request body - missing pin [422]",
          "[OK]:[422]:request body - invalid pin format [422]",
          "[OK]:[422]:user not found via username from DB [422]"],
        "SuccessTestCases":["[OK]:[200]:return auth request token, okto = 'login'"]},
      { "SubFeatureName":"Update User",
        "ApiRoute":"PUT - /en/v1/auth/update",
        "Description":[
          "accept put request with user info (name {first,last},pin, username, etc) in request body",
          "update user record in DB with user info",
          "return auth request token with login privilege"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request body must have vaild 'pin','name','username' fields"],
        "ErrorTestCases":[
          "[OK]:[422]:request header - missing auth request token",
          "[OK]:[422]:request header - invalid auth request token format",
          "[OK]:[401]:auth request token header contains username,role & okto = 'use-data'",
          "[OK]:[422]:request body - missing name, pin or username",
          "[OK]:[422]:request body - invalid pin format (4 digit as string)",
          "[OK]:[422]:user not found via username from DB"],
        "SuccessTestCases":[
          "[OK]:save updates to user record on DB",
          "[OK]:[200]:return auth request token, okto = 'use-data'"]}
    ]},
  {
    "FeatureName":"PPT User Profiles",
    "Details":[
      { "SubFeatureName":"Create Profile",
        "ApiRoute":"POST - /en/v1/profiles",
        "Description":[
          "accept post request with user profile info (username,settings,dob,bio,img,etc)",
          "create and save new profile record on DB with profile info",
          "return user profile formatted for app consumption"],
        "Requirements": [
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token (okto !== 'use-data')",
          "[OK]:[401]:invalid/inappropriate role required for operation",
          "[OK]:[422]:missing/invalid profile info (usernamr required) in req body",
          "[OK]:[422]:username already exists within DB", 
          "[OK]:[422]:invalid user profile data, rejected by DB"],
        "SuccessTestCases":[
          "[OK]:create & save new profile record on DB",
          "[OK]:[200]:return user profile formatted for app consumption"]},
      { "SubFeatureName":"Query Profiles",
        "ApiRoute":"GET - /en/v1/profiles?",
        "Description":[
          "accept get request with user profile query info",
          "fetch matching results from DB",
          "return profiles formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid query format",
          "[OK]:[422]:invalid query - rejected by DB"],
        "SuccessTestCases":[
          "[OK]:run query on profiles",
          "[OK]:run query on profiles - top level data",
          "[OK]:run query on profiles - nested data",
          "[OK]:run query on profiles - array data",
          "[OK]:pull selected data types from matching records",
          "[OK]:[200]:return user profiles formatted for app consumption"]},
      { "SubFeatureName":"Fetch Profile By Username",
        "ApiRoute":"GET - /en/v1/profiles/n/:username",
        "Description":[
          "accept get request with profile username as request param",
          "fetch profile by username from DB",
          "return profile formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'username'",
          "[OK]:[404]:profile not found"],
        "SuccessTestCases":[
          "[OK]:fetch profile by username on DB",
          "[OK]:[200]:return profile formatted for app consumption"]},
      { "SubFeatureName":"Fetch Profile By Id",
        "ApiRoute":"GET - /en/v1/profiles/:id",
        "Description":[
          "accept get request with profile id as request param",
          "fetch profile by id from DB",
          "return profile formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[404]:profile not found"],
        "SuccessTestCases":[
          "[OK]:fetch profile by id on DB",
          "[OK]:[200]:return profile formatted for app consumption"]},
      { "SubFeatureName":"Update Profile",
        "ApiRoute":"PUT - /en/v1/profiles/:id",
        "Description":[
          "accept put request with profiles updates (settings,lang,img,etc...) in req body",
          "fetch profile by id from DB",
          "update and save profile on DB",
          "return profile formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[422]:missing/invalid profile info in req body'",
          "[OK]:[404]:profile not found"],
        "SuccessTestCases":[
          "[OK]:fetch profile by id on DB",
          "[OK]:update profile - top level data",
          "[OK]:update profile - nested data, ie settings",
          "[OK]:update profile - array data",
          "[DEV]:update profile - img (jpeg/png file)",
          "[OK]:[200]:return profile formatted for app consumption"]},
      { "SubFeatureName":"Remove Profile",
        "ApiRoute":"DELETE - /en/v1/profiles/:id",
        "Description":[
          "accept del request with profile id as param",
          "fetch and remove profile from DB",
          "return remove confirmation formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[404]:profile not found"],
        "SuccessTestCases":[
          "[OK]:fetch profile by username on DB",
          "[OK]:remove profile",
          "[OK]:return remove confirmation for app consumption [200]"]}
    ]
  },
  {
    "FeatureName":"PPT Leads",
    "Details":[
      { "SubFeatureName":"Create Lead",
        "ApiRoute":"POST - /en/v1/leads",
        "Description":[
          "accept post request with lead info (campaign,contact info,contact method)",
          "create and save new lead record on DB with lead info",
          "return lead formatted for app consumption"],
        "Requirements": [
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token (okto !== 'use-data')",
          "[OK]:[401]:invalid/inappropriate role required for operation",
          "[OK]:[422]:missing/invalid lead info in req body",
          "[OK]:[422]:invalid lead data, rejected by DB"],
        "SuccessTestCases":[
          "[OK]:create & save new lead record on DB",
          "[OK]:[200]:return lead formatted for app consumption"]},
      { "SubFeatureName":"Query Leads",
        "ApiRoute":"GET - /en/v1/leads?",
        "Description":[
          "accept get request with lead query info",
          "fetch matching results from DB",
          "return leads formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid query format",
          "[OK]:[422]:invalid query - rejected by DB"],
        "SuccessTestCases":[
          "[OK]:run query on leads",
          "[OK]:run query on leads - top level data, ie. campaign",
          "[OK]:run query on leads - nested data",
          "[OK]:run query on leads - array data",
          "[OK]:pull selected data types from matching records",
          "[OK]:[200]:return leads formatted for app consumption"]},
      { "SubFeatureName":"Fetch Lead By Id",
        "ApiRoute":"GET - /en/v1/leads/:id",
        "Description":[
          "accept get request with lead id as request param",
          "fetch lead by id from DB",
          "return lead formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[404]:lead not found"],
        "SuccessTestCases":[
          "[OK]:fetch lead by id on DB",
          "[OK]:[200]:return lead formatted for app consumption"]},
      { "SubFeatureName":"Update Lead",
        "ApiRoute":"PUT - /en/v1/leads/:id",
        "Description":[
          "accept put request with leads updates (campaign,contact info,contact method,etc...) in req body",
          "fetch lead by id from DB",
          "update and save lead on DB",
          "return lead formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[422]:missing/invalid lead info in req body",
          "[OK]:[404]:lead not found"],
        "SuccessTestCases":[
          "[OK]:fetch lead by id on DB",
          "[OK]:update lead - top level data",
          "[OK]:update lead - nested data, ie settings",
          "[OK]:update lead - array data",
          "[OK]:[200]:return lead formatted for app consumption"]},
      { "SubFeatureName":"Remove Lead",
        "ApiRoute":"DELETE - /en/v1/leads/:id",
        "Description":[
          "accept del request with lead id as param",
          "fetch and remove lead from DB",
          "return remove confirmation formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[404]:lead not found"],
        "SuccessTestCases":[
          "[OK]:fetch lead by username on DB",
          "[OK]:remove lead",
          "[OK]:return remove confirmation for app consumption [200]"]}
    ]
  },
  {
    "FeatureName":"PPT Appointment Venues",
    "Details":[
      { "SubFeatureName":"Create Venue",
        "ApiRoute":"POST - /en/v1/venues",
        "Description":[
          "accept post request with venue info (name,loc info,contact,etc)",
          "create and save new venue record on DB with venue info",
          "return venue formatted for app consumption"],
        "Requirements": [
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token (okto !== 'use-data')",
          "[OK]:[401]:invalid/inappropriate role required for operation",
          "[OK]:[422]:missing/invalid venue info in req body",
          "[OK]:[422]:invalid venue data, rejected by DB"],
        "SuccessTestCases":[
          "[OK]:create & save new venue record on DB",
          "[OK]:[200]:return venue formatted for app consumption"]},
      { "SubFeatureName":"Query Venues",
        "ApiRoute":"GET - /en/v1/venues?",
        "Description":[
          "accept get request with venue query info",
          "fetch matching results from DB",
          "return venues formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid query format",
          "[OK]:[422]:invalid query - rejected by DB"],
        "SuccessTestCases":[
          "[OK]:run query on venues",
          "[OK]:run query on venues - top level data, ie. name",
          "[OK]:run query on venues - nested data",
          "[OK]:run query on venues - array data",
          "[OK]:pull selected data types from matching records",
          "[OK]:[200]:return venues formatted for app consumption"]},
      { "SubFeatureName":"Fetch Venue By Name",
        "ApiRoute":"GET - /en/v1/venues/n/:name",
        "Description":[
          "accept get request with venue name as request param",
          "fetch venue by name from DB",
          "return venue formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'name'",
          "[OK]:[404]:venue not found"],
        "SuccessTestCases":[
          "[OK]:fetch venue by name on DB",
          "[OK]:[200]:return venue formatted for app consumption"]},
      { "SubFeatureName":"Fetch Venue By Id",
        "ApiRoute":"GET - /en/v1/venues/:id",
        "Description":[
          "accept get request with venue id as request param",
          "fetch venue by id from DB",
          "return venue formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[404]:venue not found"],
        "SuccessTestCases":[
          "[OK]:fetch venue by id on DB",
          "[OK]:[200]:return venue formatted for app consumption"]},
      { "SubFeatureName":"Update Venue",
        "ApiRoute":"PUT - /en/v1/venues/:id",
        "Description":[
          "accept put request with venues updates (name,loc info,contact info,etc...) in req body",
          "fetch venue by id from DB",
          "update and save venue on DB",
          "return venue formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[422]:missing/invalid venue info in req body'",
          "[OK]:[404]:venue not found"],
        "SuccessTestCases":[
          "[OK]:fetch venue by id on DB",
          "[OK]:update venue - top level data",
          "[OK]:update venue - nested data, ie coords",
          "[OK]:update venue - array data",
          "[OK]:[200]:return venue formatted for app consumption"]},
      { "SubFeatureName":"Remove Venue",
        "ApiRoute":"DELETE - /en/v1/venues/:id",
        "Description":[
          "accept del request with venue id as param",
          "fetch and remove venue from DB",
          "return remove confirmation formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[404]:venue not found"],
        "SuccessTestCases":[
          "[OK]:fetch venue by username on DB",
          "[OK]:remove venue",
          "[OK]:return remove confirmation for app consumption [200]"]}
    ]
  },
  {
    "FeatureName":"PPT Appointments",
    "Details":[
      { "SubFeatureName":"Create Appointment",
        "ApiRoute":"POST - /en/v1/appts",
        "Description":[
          "accept post request with appt info (agent,client,date,time,venue,etc)",
          "create and save new appt record on DB with appt info",
          "return appt formatted for app consumption"],
        "Requirements": [
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token (okto !== 'use-data')",
          "[OK]:[401]:invalid/inappropriate role required for operation",
          "[OK]:[422]:missing/invalid appt info in req body",
          "[OK]:[422]:invalid appt data, rejected by DB"],
        "SuccessTestCases":[
          "[OK]:create & save new appt record on DB",
          "[OK]:[200]:return appt formatted for app consumption"]},
      { "SubFeatureName":"Query Appointments",
        "ApiRoute":"GET - /en/v1/appts?",
        "Description":[
          "accept get request with appt query info",
          "fetch matching results from DB",
          "return appts formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid query format",
          "[OK]:[422]:invalid query - rejected by DB"],
        "SuccessTestCases":[
          "[OK]:run query on appts",
          "[OK]:run query on appts - top level data, ie. date,time,client",
          "[OK]:run query on appts - nested data, ie. venue.name",
          "[OK]:run query on appts - array data",
          "[OK]:pull selected data types from matching records",
          "[OK]:[200]:return appts formatted for app consumption"]},
      { "SubFeatureName":"Fetch Appointment By Id",
        "ApiRoute":"GET - /en/v1/appts/:id",
        "Description":[
          "accept get request with appt id as request param",
          "fetch appt by id from DB",
          "return appt formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[404]:appt not found"],
        "SuccessTestCases":[
          "[OK]:fetch appt by id on DB",
          "[OK]:[200]:return appt formatted for app consumption"]},
      { "SubFeatureName":"Update Appointment",
        "ApiRoute":"PUT - /en/v1/appts/:id",
        "Description":[
          "accept put request with appts updates (agent,client,date,time,etc...) in req body",
          "fetch appt by id from DB",
          "update and save appt on DB",
          "return appt formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[422]:missing/invalid appt info in req body'",
          "[OK]:[404]:appt not found"],
        "SuccessTestCases":[
          "[OK]:fetch appt by id on DB",
          "[OK]:update appt - top level data, ie. date",
          "[OK]:update appt - nested data",
          "[OK]:update appt - array data",
          "[OK]:[200]:return appt formatted for app consumption"]},
      { "SubFeatureName":"Remove Appointment",
        "ApiRoute":"DELETE - /en/v1/appts/:id",
        "Description":[
          "accept del request with appt id as param",
          "fetch and remove appt from DB",
          "return remove confirmation formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[404]:appt not found"],
        "SuccessTestCases":[
          "[OK]:fetch appt by username on DB",
          "[OK]:remove appt",
          "[OK]:return remove confirmation for app consumption [200]"]}
    ]
  },
  {
    "FeatureName":"PPT Service Chat Messages",
    "Details":[
      { "SubFeatureName":"Create Message",
        "ApiRoute":"POST - /en/v1/msgs",
        "Description":[
          "accept post request with msg info (author,body,tytpe,,etc)",
          "create and save new msg record on DB with msg info",
          "return msg formatted for app consumption"],
        "Requirements": [
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token (okto !== 'use-data')",
          "[OK]:[401]:invalid/inappropriate role required for operation",
          "[OK]:[422]:missing/invalid msg info in req body",
          "[OK]:[422]:invalid msg data, rejected by DB"],
        "SuccessTestCases":[
          "[OK]:create & save new msg record on DB",
          "[OK]:[200]:return msg formatted for app consumption"]},
      { "SubFeatureName":"Query Messages",
        "ApiRoute":"GET - /en/v1/msgs?",
        "Description":[
          "accept get request with msg query info",
          "fetch matching results from DB",
          "return msgs formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid query format",
          "[OK]:[422]:invalid query - rejected by DB"],
        "SuccessTestCases":[
          "[OK]:run query on msgs",
          "[OK]:run query on msgs - top level data, ie. created,author",
          "[OK]:run query on msgs - nested data",
          "[OK]:run query on msgs - array data",
          "[OK]:pull selected data types from matching records",
          "[OK]:[200]:return msgs formatted for app consumption"]},
      { "SubFeatureName":"Fetch Message By Id",
        "ApiRoute":"GET - /en/v1/msgs/:id",
        "Description":[
          "accept get request with msg id as request param",
          "fetch msg by id from DB",
          "return msg formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[404]:msg not found"],
        "SuccessTestCases":[
          "[OK]:fetch msg by id on DB",
          "[OK]:[200]:return msg formatted for app consumption"]},
      { "SubFeatureName":"Update Message",
        "ApiRoute":"PUT - /en/v1/msgs/:id",
        "Description":[
          "accept put request with msgs updates (body,etc...) in req body",
          "fetch msg by id from DB",
          "update and save msg on DB",
          "return msg formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[422]:missing/invalid msg info in req body'",
          "[OK]:[404]:msg not found"],
        "SuccessTestCases":[
          "[OK]:fetch msg by id on DB",
          "[OK]:update msg - top level data, ie. body",
          "[OK]:update msg - nested data",
          "[OK]:update msg - array data",
          "[OK]:[200]:return msg formatted for app consumption"]},
      { "SubFeatureName":"Remove Message",
        "ApiRoute":"DELETE - /en/v1/msgs/:id",
        "Description":[
          "accept del request with msg id as param",
          "fetch and remove msg from DB",
          "return remove confirmation formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[404]:msg not found"],
        "SuccessTestCases":[
          "[OK]:fetch msg by username on DB",
          "[OK]:remove msg",
          "[OK]:return remove confirmation for app consumption [200]"]}
    ]
  },
  {
    "FeatureName":"PPT Service Chats",
    "Details":[
      { "SubFeatureName":"Create Chat",
        "ApiRoute":"POST - /en/v1/chats",
        "Description":[
          "accept post request with chat info (agent,client,msgs,notes,etc)",
          "create and save new chat record on DB with chat info",
          "return chat formatted for app consumption"],
        "Requirements": [
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token (okto !== 'use-data')",
          "[OK]:[401]:invalid/inappropriate role required for operation",
          "[OK]:[422]:missing/invalid chat info in req body",
          "[OK]:[422]:invalid chat data, rejected by DB"],
        "SuccessTestCases":[
          "[OK]:create & save new chat record on DB",
          "[OK]:[200]:return chat formatted for app consumption"]},
      { "SubFeatureName":"Query Chats",
        "ApiRoute":"GET - /en/v1/chats?",
        "Description":[
          "accept get request with chat query info",
          "fetch matching results from DB",
          "return chats formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid query format",
          "[OK]:[422]:invalid query - rejected by DB"],
        "SuccessTestCases":[
          "[OK]:run query on chats",
          "[OK]:run query on chats - top level data, ie. agent,client",
          "[OK]:run query on chats - nested data",
          "[OK]:run query on chats - array data",
          "[OK]:pull selected data types from matching records",
          "[OK]:[200]:return chats formatted for app consumption"]},
      { "SubFeatureName":"Fetch Chat By Id",
        "ApiRoute":"GET - /en/v1/chats/:id",
        "Description":[
          "accept get request with chat id as request param",
          "fetch chat by id from DB",
          "return chat formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[404]:chat not found"],
        "SuccessTestCases":[
          "[OK]:fetch chat by id on DB",
          "[OK]:[200]:return chat formatted for app consumption"]},
      { "SubFeatureName":"Update Chat",
        "ApiRoute":"PUT - /en/v1/chats/:id",
        "Description":[
          "accept put request with chats updates (msg,note,etc...) in req body",
          "fetch chat by id from DB",
          "update and save chat on DB",
          "return chat formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[422]:missing/invalid chat info in req body'",
          "[OK]:[404]:chat not found"],
        "SuccessTestCases":[
          "[OK]:fetch chat by id on DB",
          "[OK]:update chat - top level data",
          "[OK]:update chat - nested data",
          "[OK]:update chat - array data",
          "[OK]:update chat - msg -> create & save -> add to msgs",
          "[OK]:update chat - note -> create & save -> add to notes",
          "[OK]:[200]:return chat formatted for app consumption"]},
      { "SubFeatureName":"Remove Chat",
        "ApiRoute":"DELETE - /en/v1/chats/:id",
        "Description":[
          "accept del request with chat id as param",
          "fetch and remove chat from DB",
          "return remove confirmation formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[404]:chat not found"],
        "SuccessTestCases":[
          "[OK]:fetch chat by username on DB",
          "[OK]:remove chat",
          "[OK]:return remove confirmation for app consumption [200]"]}
    ]
  },
  {
    "FeatureName":"PPT Commissions",
    "Details":[
      { "SubFeatureName":"Create Commission",
        "ApiRoute":"POST - /en/v1/comms",
        "Description":[
          "accept post request with comm info (payer,payee,amt,reason,refId,etc)",
          "create and save new comm record on DB with comm info",
          "return comm formatted for app consumption"],
        "Requirements": [
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token (okto !== 'use-data')",
          "[OK]:[401]:invalid/inappropriate role required for operation",
          "[OK]:[422]:missing/invalid comm info in req body",
          "[OK]:[422]:invalid comm data, rejected by DB"],
        "SuccessTestCases":[
          "[OK]:create & save new comm record on DB",
          "[OK]:[200]:return comm formatted for app consumption"]},
      { "SubFeatureName":"Query Commissions",
        "ApiRoute":"GET - /en/v1/comms?",
        "Description":[
          "accept get request with comm query info",
          "fetch matching results from DB",
          "return comms formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid query format",
          "[OK]:[422]:invalid query - rejected by DB"],
        "SuccessTestCases":[
          "[OK]:run query on comms - top level data, ie. payer,payee,amt > x",
          "[OK]:run query on comms - nested data",
          "[OK]:run query on comms - array data",
          "[OK]:pull selected data types from matching records",
          "[OK]:[200]:return comms formatted for app consumption"]},
      { "SubFeatureName":"Fetch Commission By Id",
        "ApiRoute":"GET - /en/v1/comms/:id",
        "Description":[
          "accept get request with comm id as request param",
          "fetch comm by id from DB",
          "return comm formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[404]:comm not found"],
        "SuccessTestCases":[
          "[OK]:fetch comm by id on DB",
          "[OK]:[200]:return comm formatted for app consumption"]},
      { "SubFeatureName":"Update Commission",
        "ApiRoute":"PUT - /en/v1/comms/:id",
        "Description":[
          "accept put request with comms updates (payer,payee,amt,reason,refId,etc...) in req body",
          "fetch comm by id from DB",
          "update and save comm on DB",
          "return comm formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[422]:missing/invalid comm info in req body'",
          "[OK]:[404]:comm not found"],
        "SuccessTestCases":[
          "[OK]:fetch comm by id on DB",
          "[OK]:update comm - top level data",
          "[OK]:update comm - nested data, ie settings",
          "[OK]:update comm - array data",
          "[OK]:[200]:return comm formatted for app consumption"]},
      { "SubFeatureName":"Remove Commission",
        "ApiRoute":"DELETE - /en/v1/comms/:id",
        "Description":[
          "accept del request with comm id as param",
          "fetch comm by id from DB",
          "remove comm from DB",
          "return remove confirmation formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header w/ valid user credentials",
          "[OK]:User must have 'loggedin' status",
          "[OK]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[OK]:[401]:missing or invalid api token",
          "[OK]:[422]:invalid req param 'id'",
          "[OK]:[404]:comm not found"],
        "SuccessTestCases":[
          "[OK]:fetch comm by username on DB",
          "[OK]:remove comm",
          "[OK]:return remove confirmation for app consumption [200]"]}
    ]
  },
  {
    "FeatureName":"PPT File Uploads",
    "Details":[
      { "SubFeatureName":"Upload File",
        "ApiRoute":"POST - /en/v1/uploads",
        "Description":[
          "accept post request with attached file",
          "create and save new file on DB with file info",
          "return file upload confirmation formatted for app consumption"],
        "Requirements": [
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header",
          "[OK]:Auth token must have user credentials",
          "[OK]:User must have 'loggedin' status"],
        "ErrorTestCases":[
          "[OK]:missing or invalid api token [401]",
          "[DEV]:invalid file metadata [422]", 
          "[OK]:invalid file data, rejected by DB [422]"],
        "SuccessTestCases":[
          "[OK]:create & save new file in GridBucket on DB",
          "[OK]:return file upload confirmation formatted for app consumption"]},
      { "SubFeatureName":"Fetch File Upload By Id",
        "ApiRoute":"GET - /en/v1/uploads/:id",
        "Description":[
          "accept get request with file id as request param",
          "fetch file by id from DB",
          "return file formatted for app consumption"],
        "Requirements":[
          "[OK]:Request must pass Base API security",
          "[OK]:Request must have authorization header",
          "[OK]:Auth token must have user credentials",
          "[OK]:User must have 'loggedin' status"],
        "ErrorTestCases":[
          "[OK]:missing or invalid api token [401]",
          "[OK]:invalid req param 'id' [422]",
          "[OK]:file not found [404]"],
        "SuccessTestCases":[
          "[OK]:fetch file by id via GridBucket on DB",
          "[OK]:return file formatted for app consumption [200]"]}
    ]
  },
  {
    "FeatureName":"PPT Document Reviews",
    "Details":[
      { "SubFeatureName":"Create Document Review",
        "ApiRoute":"POST - /en/v1/doc-reviews",
        "Description":[
          "accept post request with doc-review info (doctype,agent?,refId?,dueDate?,fileUrl?,etc)",
          "create and save new doc-review record on DB with doc-review info",
          "return doc-review formatted for app consumption"],
        "Requirements": [
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token (okto !== 'use-data')",
          "[DEV]:[401]:invalid/inappropriate role required for operation",
          "[DEV]:[422]:missing/invalid doc-review info in req body", 
          "[DEV]:[422]:invalid doc-review data, rejected by DB"],
        "SuccessTestCases":[
          "[DEV]:create & save new doc-review record on DB",
          "[DEV]:[200]:return doc-review formatted for app consumption"]},
      { "SubFeatureName":"Query Document Reviews",
        "ApiRoute":"GET - /en/v1/doc-reviews?",
        "Description":[
          "accept get request with doc-review query info",
          "fetch matching results from DB",
          "return doc-reviews formatted for app consumption"],
        "Requirements":[
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid query format",
          "[DEV]:[422]:invalid query - rejected by DB"],
        "SuccessTestCases":[
          "[DEV]:run query on doc-reviews",
          "[DEV]:run query on doc-reviews - top level data, ie. doctype,agent,refId,dueDate > x",
          "[DEV]:run query on doc-reviews - nested data",
          "[DEV]:run query on doc-reviews - array data",
          "[DEV]:pull selected data types from matching records",
          "[DEV]:[200]:return doc-reviews formatted for app consumption"]},
      { "SubFeatureName":"Fetch Document Review By Title",
        "ApiRoute":"GET - /en/v1/doc-reviews/n/:title",
        "Description":[
          "accept get request with doc-review title as param",
          "fetch doc-review by title from DB",
          "return doc-review formatted for app consumption"],
        "Requirements":[
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid req param 'title'",
          "[DEV]:[404]:doc-review not found"],
        "SuccessTestCases":[
          "[DEV]:fetch doc-review by title on DB",
          "[DEV]:[200]:return doc-review formatted for app consumption"]},
      { "SubFeatureName":"Fetch Document Review By Id",
        "ApiRoute":"GET - /en/v1/doc-reviews/:id",
        "Description":[
          "accept get request with doc-review id as request param",
          "fetch doc-review by id from DB",
          "return doc-review formatted for app consumption"],
        "Requirements":[
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid req param 'id'",
          "[DEV]:[404]:doc-review not found"],
        "SuccessTestCases":[
          "[DEV]:fetch doc-review by id on DB",
          "[DEV]:[200]:return doc-review formatted for app consumption"]},
      { "SubFeatureName":"Update Document Review",
        "ApiRoute":"PUT - /en/v1/doc-reviews/:id",
        "Description":[
          "accept put request with doc-reviews updates (doctype,agent,refId,dueDate,fileUrl,etc...) in req body",
          "fetch doc-review by id from DB",
          "update and save doc-review on DB",
          "return doc-review formatted for app consumption"],
        "Requirements":[
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid req param 'id'",
          "[DEV]:[422]:missing/invalid doc-review info in req body'",
          "[DEV]:[404]:doc-review not found"],
        "SuccessTestCases":[
          "[DEV]:fetch doc-review by id on DB",
          "[DEV]:update doc-review - top level data, ie. doctype,agent,refId,dueDate,fileUrl",
          "[DEV]:update doc-review - nested data",
          "[DEV]:update doc-review - array data",
          "[DEV]:update doc-review - file (pdf,docx,etc) --> upload file?",
          "[DEV]:[200]:return doc-review formatted for app consumption"]},
      { "SubFeatureName":"Remove Document Review",
        "ApiRoute":"DELETE - /en/v1/doc-reviews/:id",
        "Description":[
          "accept del request with doc-review id as param",
          "fetch and remove doc-review from DB",
          "return remove confirmation formatted for app consumption"],
        "Requirements":[
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid req param 'id'",
          "[DEV]:[404]:doc-review not found"],
        "SuccessTestCases":[
          "[DEV]:fetch doc-review by username on DB",
          "[DEV]:remove doc-review",
          "[DEV]:return remove confirmation for app consumption [200]"]}
    ]
  },
  {
    "FeatureName":"PPT Misc Tasks",
    "Details":[
      { "SubFeatureName":"Create Misc Task",
        "ApiRoute":"POST - /en/v1/tasks",
        "Description":[
          "accept post request with task info (type,owner,agent,refId,dueDate,etc)",
          "create and save new task record on DB with task info",
          "return task formatted for app consumption"],
        "Requirements": [
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token (okto !== 'use-data')",
          "[DEV]:[401]:invalid/inappropriate role required for operation",
          "[DEV]:[422]:missing/invalid task info in req body",
          "[DEV]:[422]:invalid task data, rejected by DB"],
        "SuccessTestCases":[
          "[DEV]:create & save new task record on DB",
          "[DEV]:[200]:return task formatted for app consumption"]},
      { "SubFeatureName":"Query Misc Tasks",
        "ApiRoute":"GET - /en/v1/tasks?",
        "Description":[
          "accept get request with task query info",
          "fetch matching results from DB",
          "return tasks formatted for app consumption"],
        "Requirements":[
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid query format",
          "[DEV]:[422]:invalid query - rejected by DB"],
        "SuccessTestCases":[
          "[DEV]:run query on tasks - top level data, ie. type,owner,agent,refId,dueDate",
          "[DEV]:run query on tasks - nested data",
          "[DEV]:run query on tasks - array data",
          "[DEV]:pull selected data types from matching records",
          "[DEV]:[200]:return tasks formatted for app consumption"]},
      { "SubFeatureName":"Fetch Misc Task By Id",
        "ApiRoute":"GET - /en/v1/tasks/:id",
        "Description":[
          "accept get request with task id as request param",
          "fetch task by id from DB",
          "return task formatted for app consumption"],
        "Requirements":[
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid req param 'id'",
          "[DEV]:[404]:task not found"],
        "SuccessTestCases":[
          "[DEV]:fetch task by id on DB",
          "[DEV]:[200]:return task formatted for app consumption"]},
      { "SubFeatureName":"Update Misc Task",
        "ApiRoute":"PUT - /en/v1/tasks/:id",
        "Description":[
          "accept put request with tasks updates (type,owner,agent,refId,dueDate,etc...) in req body",
          "fetch task by id from DB",
          "update and save task on DB",
          "return task formatted for app consumption"],
        "Requirements":[
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid req param 'id'",
          "[DEV]:[422]:missing/invalid task info in req body'",
          "[DEV]:[404]:task not found"],
        "SuccessTestCases":[
          "[DEV]:fetch task by id on DB",
          "[DEV]:update task - top level data, ie. type,owner,agent,refId,dueDate",
          "[DEV]:update task - nested data",
          "[DEV]:update task - array data",
          "[DEV]:update task - img (jpeg/png file)",
          "[DEV]:[200]:return task formatted for app consumption"]},
      { "SubFeatureName":"Remove Misc Task",
        "ApiRoute":"DELETE - /en/v1/tasks/:id",
        "Description":[
          "accept del request with task id as param",
          "fetch task and remove task from DB",
          "return remove confirmation formatted for app consumption"],
        "Requirements":[
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid req param 'id'",
          "[DEV]:[404]:task not found"],
        "SuccessTestCases":[
          "[DEV]:fetch task by username on DB",
          "[DEV]:remove task",
          "[DEV]:return remove confirmation for app consumption [200]"]}
    ]
  },
  {
    "FeatureName":"PPT Notifications",
    "Details":[
      { "SubFeatureName":"Create Notification",
        "ApiRoute":"POST - /en/v1/notifications",
        "Description":[
          "accept post request with notification info (recipient,destination,method,body,sendAt,etc)",
          "create and save new notification record on DB with notification info",
          "return notification formatted for app consumption"],
        "Requirements": [
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token (okto !== 'use-data')",
          "[DEV]:[401]:invalid/inappropriate role required for operation",
          "[DEV]:[422]:missing/invalid notification info in req body", 
          "[DEV]:[422]:invalid notification data, rejected by DB"],
        "SuccessTestCases":[
          "[DEV]:create & save new notification record on DB",
          "[DEV]:[200]:return notification formatted for app consumption"]},
      { "SubFeatureName":"Query Notifications",
        "ApiRoute":"GET - /en/v1/notifications?",
        "Description":[
          "accept get request with notification query info",
          "fetch matching results from DB",
          "return notifications formatted for app consumption"],
        "Requirements":[
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid query format",
          "[DEV]:[422]:invalid query - rejected by DB"],
        "SuccessTestCases":[
          "[DEV]:run query on notifications - top level data, ie. recipient,destination,method,body,sendAt",
          "[DEV]:run query on notifications - nested data",
          "[DEV]:run query on notifications - array data",
          "[DEV]:pull selected data types from matching records",
          "[DEV]:[200]:return notifications formatted for app consumption"]},
      { "SubFeatureName":"Fetch Notification By Id",
        "ApiRoute":"GET - /en/v1/notifications/:id",
        "Description":[
          "accept get request with notification id as request param",
          "fetch notification by id from DB",
          "return notification formatted for app consumption"],
        "Requirements":[
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid req param 'id'",
          "[DEV]:[404]:notification not found"],
        "SuccessTestCases":[
          "[DEV]:fetch notification by id on DB",
          "[DEV]:[200]:return notification formatted for app consumption"]},
      { "SubFeatureName":"Update Notification",
        "ApiRoute":"PUT - /en/v1/notifications/:id",
        "Description":[
          "accept put request with notifications updates (recipient,destination,method,body,sendAt,etc...) in req body",
          "fetch notification by id from DB",
          "update and save notification on DB",
          "return notification formatted for app consumption"],
        "Requirements":[
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid req param 'id'",
          "[DEV]:[422]:missing/invalid notification info in req body'",
          "[DEV]:[404]:notification not found"],
        "SuccessTestCases":[
          "[DEV]:fetch notification by id on DB",
          "[DEV]:update notification - top level data, ie. recipient,destination,method,body,sendAt",
          "[DEV]:update notification - nested data",
          "[DEV]:update notification - array data",
          "[DEV]:[200]:return notification formatted for app consumption"]},
      { "SubFeatureName":"Remove Notification",
        "ApiRoute":"DELETE - /en/v1/notifications/:id",
        "Description":[
          "accept del request with notification id as param",
          "fetch and remove notification from DB",
          "return remove confirmation formatted for app consumption"],
        "Requirements":[
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must be appropriate for operation"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid req param 'id'",
          "[DEV]:[404]:notification not found"],
        "SuccessTestCases":[
          "[DEV]:fetch notification by username on DB",
          "[DEV]:remove notification",
          "[DEV]:return remove confirmation for app consumption [200]"]}
    ]
  },
  {
    "FeatureName":"PPT Notifier",
    "Details":[
      { "SubFeatureName":"Send Email",
        "ApiRoute":"POST - /en/v1/notify/e",
        "Description":[
          "accept post request with notification info",
          "create and save new notification record on DB",
          "send notification via email, update record w/ confirmation and save",
          "return notification formatted for app consumption"],
        "Requirements": [
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must must be 'SUPER' or higher"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid notification data", 
          "[DEV]:[422]:invalid notification data, rejected by DB"],
        "SuccessTestCases":[
          "[DEV]:create & save new notification on DB",
          "[DEV]:send notification via email and await confirmation",
          "[DEV]:update notification with confirmation data, save in DB",
          "[DEV]:[200]:return notification formatted for app consumption"]},
      { "SubFeatureName":"Send Text",
        "ApiRoute":"POST - /en/v1/notify/e",
        "Description":[
          "accept post request with notificaion info",
          "create and save new notification record on DB",
          "send notification via text, update and save",
          "return notification formatted for app consumption"],
        "Requirements":[
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must must be 'SUPER' or higher"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid notification data", 
          "[DEV]:[422]:invalid notification data, rejected by DB"],
        "SuccessTestCases":[
          "[DEV]:create & save new notification on DB",
          "[DEV]:send notification via text and await confirmation",
          "[DEV]:update notification with confirmation data, save in DB",
          "[DEV]:[200]:return notification formatted for app consumption"]},
      { "SubFeatureName":"Send Push",
        "ApiRoute":"POST - /en/v1/notify/e",
        "Description":[
          "accept post request with notificaion info",
          "create and save new notification record on DB",
          "send notification via push, update and save",
          "return notification formatted for app consumption"],
        "Requirements":[
          "[DEV]:Request must pass Base API security",
          "[DEV]:Request must have authorization header w/ valid user credentials",
          "[DEV]:User must have 'loggedin' status",
          "[DEV]:User role must must be 'SUPER' or higher"],
        "ErrorTestCases":[
          "[DEV]:[401]:missing or invalid api token",
          "[DEV]:[422]:invalid notification data", 
          "[DEV]:[422]:invalid notification data, rejected by DB"],
        "SuccessTestCases":[
          "[DEV]:create & save new notification on DB",
          "[DEV]:send notification via push and await confirmation",
          "[DEV]:update notification with confirmation data, save in DB",
          "[DEV]:[200]:return notification formatted for app consumption"]}
    ]
  }
]