{
  "version": "1.4",
  "metadata": {
    "app": "nytem-2021/appland",
    "language": {
      "name": "ruby",
      "engine": "ruby",
      "version": "2.6.6"
    },
    "client": {
      "name": "appmap",
      "url": "https://github.com/applandinc/appmap-ruby",
      "version": "0.42.0"
    },
    "frameworks": [
      {
        "name": "rails",
        "version": "5.2.4.2"
      },
      {
        "name": "rspec",
        "version": "3.9.1"
      }
    ],
    "git": {
      "repository": "git@github.com:applandinc/appland.git",
      "branch": "swagger",
      "commit": "d82ba25ed71e5086c39becb3a3ae2cfc2a3571b6",
      "status": [
        "M Gemfile.lock",
        "?? 20210310072459.appmap.json"
      ],
      "git_last_annotated_tag": null,
      "git_last_tag": "v0.22.0",
      "git_commits_since_last_annotated_tag": null,
      "git_commits_since_last_tag": 0
    },
    "name": "API::ScenariosController .search logged in validates mapsets parameter",
    "source_location": "spec/requests/api_scenarios_search_spec.rb",
    "recorder": {
      "name": "rspec"
    },
    "fingerprints": [
      {
        "appmap_digest": "ecba8216b6c5465f043fa3d92e460456c7a3a809d40615c08417a6d21eb22885",
        "canonicalization_algorithm": "info_v1",
        "digest": "f08e6ccda5e25c56fab21e86d3e1d3e107242d6514289f6ae222f6601b018172",
        "fingerprint_algorithm": "sha256"
      },
      {
        "appmap_digest": "ecba8216b6c5465f043fa3d92e460456c7a3a809d40615c08417a6d21eb22885",
        "canonicalization_algorithm": "update_v1",
        "digest": "1a9428c71a173357f1dc23b594a5d705c9ea3945e9da0e6b1f8a26d9cef2f851",
        "fingerprint_algorithm": "sha256"
      },
      {
        "appmap_digest": "ecba8216b6c5465f043fa3d92e460456c7a3a809d40615c08417a6d21eb22885",
        "canonicalization_algorithm": "trace_v1",
        "digest": "46b6e5a47db895a206460bef2c91fae58bb05cd637127ca1df68fcd0138cf7da",
        "fingerprint_algorithm": "sha256"
      }
    ]
  },
  "classMap": [
    {
      "name": "app/models",
      "type": "package",
      "children": [
        {
          "name": "ApiKey",
          "type": "class",
          "children": [
            {
              "name": "issue",
              "type": "function",
              "location": "app/models/api_key.rb:28",
              "static": true,
              "source": "    def issue(login, description: nil, encode: true)\n      api_key = DAO::ApiKey.new.tap do |api_key|\n        api_key.login = login\n        api_key.description = description if description.present?\n        api_key.save\n      end\n\n      return encode(api_key) if encode\n\n      api_key\n    end\n"
            },
            {
              "name": "encode",
              "type": "function",
              "location": "app/models/api_key.rb:20",
              "static": true,
              "source": "    def encode(api_key)\n      Base64.urlsafe_encode64([api_key.login, api_key.key].join(SEPARATOR), padding: false)\n    end\n"
            },
            {
              "name": "authenticate",
              "type": "function",
              "location": "app/models/api_key.rb:52",
              "static": true,
              "labels": [
                "provider.authentication"
              ],
              "comment": "# @labels provider.authentication\n",
              "source": "    def authenticate(api_key)\n      login, key = decode(api_key)\n      result = DAO::ApiKey.where(login: login).match(key)\n\n      if result.present?\n        touch(result)\n        User::Show.new(result.user)\n      else\n        nil\n      end\n    end\n"
            },
            {
              "name": "decode",
              "type": "function",
              "location": "app/models/api_key.rb:24",
              "static": true,
              "source": "    def decode(api_key)\n      Base64.urlsafe_decode64(api_key).split(SEPARATOR)\n    end\n"
            },
            {
              "name": "touch",
              "type": "function",
              "location": "app/models/api_key.rb:11",
              "static": true,
              "source": "    def touch(api_key)\n      if api_key.last_used.nil? || api_key.last_used > 15.minutes.ago\n        api_key.last_used = Time.now\n        api_key.save_changes\n      end\n\n      api_key\n    end\n"
            }
          ]
        }
      ]
    },
    {
      "name": "action_pack",
      "type": "package",
      "children": [
        {
          "name": "ActionDispatch",
          "type": "class",
          "children": [
            {
              "name": "Cookies",
              "type": "class",
              "children": [
                {
                  "name": "CookieJar",
                  "type": "class",
                  "children": [
                    {
                      "name": "update",
                      "type": "function",
                      "location": "/Users/kgilpin/tmp/appland/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.4.2/lib/action_dispatch/middleware/cookies.rb:344",
                      "static": false,
                      "labels": [
                        "provider.http.cookie"
                      ],
                      "source": "      def update(other_hash)\n        @cookies.update other_hash.stringify_keys\n        self\n      end\n"
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "name": "app/controllers",
      "type": "package",
      "children": [
        {
          "name": "AnonymousAccess",
          "type": "class",
          "children": [
            {
              "name": "anonymous_access?",
              "type": "function",
              "location": "app/controllers/concerns/anonymous_access.rb:9",
              "static": false,
              "source": "  def anonymous_access?\n    @anonymous_access\n  end\n"
            }
          ]
        },
        {
          "name": "API",
          "type": "class",
          "children": [
            {
              "name": "ScenariosController",
              "type": "class",
              "children": [
                {
                  "name": "index",
                  "type": "function",
                  "location": "app/controllers/api/scenarios_controller.rb:17",
                  "static": false,
                  "source": "    def index\n      raise Exceptions::InvalidArguments.new('search', 'mapsets are required') unless params[:mapsets].present?\n\n      validate_params_intersection('labels', 'not_labels')\n      validate_params_intersection('code_objects', 'not_code_objects')\n\n      scenarios = search_scope(Scenario, scope: Search::SCOPE_MEMBERSHIP).search_api(params)\n      render json: scenarios, status: :ok\n    end\n"
                }
              ]
            }
          ]
        },
        {
          "name": "APIController",
          "type": "class",
          "children": [
            {
              "name": "invalid_arguments",
              "type": "function",
              "location": "app/controllers/api_controller.rb:36",
              "static": false,
              "comment": "# rubocop:enable Metrics/MethodLength\n",
              "source": "  def invalid_arguments(exception)\n    error = {\n      code: 'invalid',\n      target: exception.kind,\n      message: exception.message\n    }\n    render json: { error: error }, status: 422\n  end\n"
            }
          ]
        }
      ]
    },
    {
      "name": "json",
      "type": "package",
      "children": [
        {
          "name": "JSON",
          "type": "class",
          "children": [
            {
              "name": "Ext",
              "type": "class",
              "children": [
                {
                  "name": "Generator",
                  "type": "class",
                  "children": [
                    {
                      "name": "State",
                      "type": "class",
                      "children": [
                        {
                          "name": "generate",
                          "type": "function",
                          "location": "JSON::Ext::Generator::State#generate",
                          "static": false,
                          "labels": [
                            "format.json",
                            "provider.serialization"
                          ]
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  ],
  "events": [
    {
      "id": 64361,
      "event": "call",
      "thread_id": 70223206228000,
      "defined_class": "ApiKey",
      "method_id": "issue",
      "path": "app/models/api_key.rb",
      "lineno": 28,
      "static": true,
      "parameters": [
        {
          "name": "login",
          "class": "String",
          "object_id": 70222950040420,
          "value": "alice",
          "kind": "req"
        },
        {
          "name": "description",
          "class": "NilClass",
          "object_id": 8,
          "value": null,
          "kind": "key"
        },
        {
          "name": "encode",
          "class": "NilClass",
          "object_id": 8,
          "value": null,
          "kind": "key"
        }
      ],
      "receiver": {
        "class": "Class",
        "object_id": 70222285939160,
        "value": "ApiKey"
      }
    },
    {
      "id": 64362,
      "event": "call",
      "thread_id": 70223206228000,
      "sql_query": {
        "sql": "INSERT INTO \"api_keys\" (\"login\") VALUES ('alice') RETURNING *",
        "database_type": "postgres",
        "server_version": 120003
      }
    },
    {
      "id": 64363,
      "event": "return",
      "thread_id": 70223206228000,
      "parent_id": 64362,
      "elapsed": 0.001019
    },
    {
      "id": 64364,
      "event": "call",
      "thread_id": 70223206228000,
      "defined_class": "ApiKey",
      "method_id": "encode",
      "path": "app/models/api_key.rb",
      "lineno": 20,
      "static": true,
      "parameters": [
        {
          "name": "api_key",
          "class": "DAO::ApiKey",
          "object_id": 70221864489580,
          "value": "#<DAO::ApiKey:0x00007fbb9a93a4d8>",
          "kind": "req"
        }
      ],
      "receiver": {
        "class": "Class",
        "object_id": 70222285939160,
        "value": "ApiKey"
      }
    },
    {
      "id": 64365,
      "event": "return",
      "thread_id": 70223206228000,
      "parent_id": 64364,
      "elapsed": 0.00002,
      "return_value": {
        "class": "String",
        "value": "YWxpY2U6ZDJhZGYxZjktZTk0OC00NDc0LThjN2ItNWFjYWRhZjBkZmVk",
        "object_id": 70221744744660
      }
    },
    {
      "id": 64366,
      "event": "return",
      "thread_id": 70223206228000,
      "parent_id": 64361,
      "elapsed": 0.005067,
      "return_value": {
        "class": "String",
        "value": "YWxpY2U6ZDJhZGYxZjktZTk0OC00NDc0LThjN2ItNWFjYWRhZjBkZmVk",
        "object_id": 70221744744660
      }
    },
    {
      "id": 64367,
      "event": "call",
      "thread_id": 70223206228000,
      "http_server_request": {
        "request_method": "GET",
        "path_info": "/api/scenarios",
        "normalized_path_info": "/api/scenarios(.:format)",
        "authorization": "Bearer YWxpY2U6ZDJhZGYxZjktZTk0OC00NDc0LThjN2ItNWFjYWRhZjBkZmVk"
      },
      "message": [
        {
          "name": "code_objects",
          "class": "Array",
          "value": "[\"controllers\"]",
          "object_id": 70221744793940
        },
        {
          "name": "controller",
          "class": "String",
          "value": "api/scenarios",
          "object_id": 70222270836680
        },
        {
          "name": "action",
          "class": "String",
          "value": "index",
          "object_id": 70222270839940
        }
      ]
    },
    {
      "id": 64368,
      "event": "call",
      "thread_id": 70223206228000,
      "defined_class": "ActionDispatch::Cookies::CookieJar",
      "method_id": "update",
      "path": "/Users/kgilpin/tmp/appland/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.4.2/lib/action_dispatch/middleware/cookies.rb",
      "lineno": 344,
      "static": false,
      "parameters": [
        {
          "name": "other_hash",
          "class": "Hash",
          "object_id": 70221744765800,
          "value": "{}",
          "kind": "req"
        }
      ],
      "receiver": {
        "class": "ActionDispatch::Cookies::CookieJar",
        "object_id": 70221744791620,
        "value": "#<ActionDispatch::Cookies::CookieJar:0x00007fbb8c4ec088>"
      }
    },
    {
      "id": 64369,
      "event": "return",
      "thread_id": 70223206228000,
      "parent_id": 64368,
      "elapsed": 0.000008,
      "return_value": {
        "class": "ActionDispatch::Cookies::CookieJar",
        "value": "#<ActionDispatch::Cookies::CookieJar:0x00007fbb8c4ec088>",
        "object_id": 70221744791620
      }
    },
    {
      "id": 64370,
      "event": "call",
      "thread_id": 70223206228000,
      "defined_class": "AnonymousAccess",
      "method_id": "anonymous_access?",
      "path": "app/controllers/concerns/anonymous_access.rb",
      "lineno": 9,
      "static": false,
      "parameters": [],
      "receiver": {
        "class": "API::ScenariosController",
        "object_id": 70221744782320,
        "value": "#<API::ScenariosController:0x00007fbb8c4e77e0>"
      }
    },
    {
      "id": 64371,
      "event": "return",
      "thread_id": 70223206228000,
      "parent_id": 64370,
      "elapsed": 0.000008
    },
    {
      "id": 64372,
      "event": "call",
      "thread_id": 70223206228000,
      "defined_class": "ApiKey",
      "method_id": "authenticate",
      "path": "app/models/api_key.rb",
      "lineno": 52,
      "static": true,
      "parameters": [
        {
          "name": "api_key",
          "class": "String",
          "object_id": 70221744811300,
          "value": "YWxpY2U6ZDJhZGYxZjktZTk0OC00NDc0LThjN2ItNWFjYWRhZjBkZmVk",
          "kind": "req"
        }
      ],
      "receiver": {
        "class": "Class",
        "object_id": 70222285939160,
        "value": "ApiKey"
      }
    },
    {
      "id": 64373,
      "event": "call",
      "thread_id": 70223206228000,
      "defined_class": "ApiKey",
      "method_id": "decode",
      "path": "app/models/api_key.rb",
      "lineno": 24,
      "static": true,
      "parameters": [
        {
          "name": "api_key",
          "class": "String",
          "object_id": 70221744811300,
          "value": "YWxpY2U6ZDJhZGYxZjktZTk0OC00NDc0LThjN2ItNWFjYWRhZjBkZmVk",
          "kind": "req"
        }
      ],
      "receiver": {
        "class": "Class",
        "object_id": 70222285939160,
        "value": "ApiKey"
      }
    },
    {
      "id": 64374,
      "event": "return",
      "thread_id": 70223206228000,
      "parent_id": 64373,
      "elapsed": 0.000012,
      "return_value": {
        "class": "Array",
        "value": "[\"alice\", \"d2adf1f9-e948-4474-8c7b-5acadaf0dfed\"]",
        "object_id": 70221744808360
      }
    },
    {
      "id": 64375,
      "event": "call",
      "thread_id": 70223206228000,
      "sql_query": {
        "sql": "SELECT * FROM \"api_keys\" WHERE (\"login\" = 'alice')",
        "database_type": "postgres",
        "server_version": 120003
      }
    },
    {
      "id": 64376,
      "event": "return",
      "thread_id": 70223206228000,
      "parent_id": 64375,
      "elapsed": 0.001088
    },
    {
      "id": 64377,
      "event": "call",
      "thread_id": 70223206228000,
      "defined_class": "ApiKey",
      "method_id": "touch",
      "path": "app/models/api_key.rb",
      "lineno": 11,
      "static": true,
      "parameters": [
        {
          "name": "api_key",
          "class": "DAO::ApiKey",
          "object_id": 70221735180940,
          "value": "#<DAO::ApiKey:0x00007fbb8b297518>",
          "kind": "req"
        }
      ],
      "receiver": {
        "class": "Class",
        "object_id": 70222285939160,
        "value": "ApiKey"
      }
    },
    {
      "id": 64378,
      "event": "call",
      "thread_id": 70223206228000,
      "sql_query": {
        "sql": "UPDATE \"api_keys\" SET \"last_used\" = '2021-03-27 15:38:44.482755+0000' WHERE (\"id\" = 10)",
        "database_type": "postgres",
        "server_version": 120003
      }
    },
    {
      "id": 64379,
      "event": "return",
      "thread_id": 70223206228000,
      "parent_id": 64378,
      "elapsed": 0.001079
    },
    {
      "id": 64380,
      "event": "return",
      "thread_id": 70223206228000,
      "parent_id": 64377,
      "elapsed": 0.005874,
      "return_value": {
        "class": "DAO::ApiKey",
        "value": "#<DAO::ApiKey:0x00007fbb8b297518>",
        "object_id": 70221735180940
      }
    },
    {
      "id": 64381,
      "event": "call",
      "thread_id": 70223206228000,
      "sql_query": {
        "sql": "SELECT * FROM \"users\" WHERE (\"users\".\"login\" = 'alice') LIMIT 1",
        "database_type": "postgres",
        "server_version": 120003
      }
    },
    {
      "id": 64382,
      "event": "return",
      "thread_id": 70223206228000,
      "parent_id": 64381,
      "elapsed": 0.000856
    },
    {
      "id": 64383,
      "event": "return",
      "thread_id": 70223206228000,
      "parent_id": 64372,
      "elapsed": 0.016561,
      "return_value": {
        "class": "User::Show",
        "value": "#<User::Show:0x00007fbb8a8941b0>",
        "object_id": 70221729931480
      }
    },
    {
      "id": 64384,
      "event": "call",
      "thread_id": 70223206228000,
      "defined_class": "API::ScenariosController",
      "method_id": "index",
      "path": "app/controllers/api/scenarios_controller.rb",
      "lineno": 17,
      "static": false,
      "parameters": [],
      "receiver": {
        "class": "API::ScenariosController",
        "object_id": 70221744782320,
        "value": "#<API::ScenariosController:0x00007fbb8c4e77e0>"
      }
    },
    {
      "id": 64385,
      "event": "return",
      "thread_id": 70223206228000,
      "parent_id": 64384,
      "elapsed": 0.000158,
      "exceptions": [
        {
          "class": "Exceptions::InvalidArguments",
          "message": "mapsets are required",
          "object_id": 70221729953920,
          "path": "/Users/kgilpin/source/appland/appland/app/controllers/api/scenarios_controller.rb",
          "lineno": 18
        }
      ]
    },
    {
      "id": 64386,
      "event": "call",
      "thread_id": 70223206228000,
      "defined_class": "APIController",
      "method_id": "invalid_arguments",
      "path": "app/controllers/api_controller.rb",
      "lineno": 36,
      "static": false,
      "parameters": [
        {
          "name": "exception",
          "class": "Exceptions::InvalidArguments",
          "object_id": 70221729953920,
          "value": "mapsets are required",
          "kind": "req"
        }
      ],
      "receiver": {
        "class": "API::ScenariosController",
        "object_id": 70221744782320,
        "value": "#<API::ScenariosController:0x00007fbb8c4e77e0>"
      }
    },
    {
      "id": 64387,
      "event": "call",
      "thread_id": 70223206228000,
      "defined_class": "JSON::Ext::Generator::State",
      "method_id": "generate",
      "path": "JSON::Ext::Generator::State#generate",
      "static": false,
      "parameters": [
        {
          "name": "arg",
          "class": "Hash",
          "object_id": 70221729969200,
          "value": "{\"error\"=>{\"code\"=>\"invalid\", \"target\"=>\"search\", \"message\"=>\"mapsets are required\"}}",
          "kind": "req"
        }
      ],
      "receiver": {
        "class": "JSON::Ext::Generator::State",
        "object_id": 70221729969160,
        "value": "#<JSON::Ext::Generator::State:0x00007fbb8a8a6810>"
      }
    },
    {
      "id": 64388,
      "event": "return",
      "thread_id": 70223206228000,
      "parent_id": 64387,
      "elapsed": 0.000029,
      "return_value": {
        "class": "String",
        "value": "{\"error\":{\"code\":\"invalid\",\"target\":\"search\",\"message\":\"mapsets are required\"}}",
        "object_id": 70221729966980
      }
    },
    {
      "id": 64389,
      "event": "return",
      "thread_id": 70223206228000,
      "parent_id": 64386,
      "elapsed": 0.000227,
      "return_value": {
        "class": "String",
        "value": "{\"error\":{\"code\":\"invalid\",\"target\":\"search\",\"message\":\"mapsets are required\"}}",
        "object_id": 70221729966980
      }
    },
    {
      "id": 64390,
      "event": "return",
      "thread_id": 70223206228000,
      "parent_id": 64367,
      "elapsed": 0.018198,
      "http_server_response": {
        "status": 422,
        "mime_type": "application/json; charset=utf-8"
      }
    }
  ]
}