@salesforce/afv-skills 1.34.0 → 1.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/package.json +1 -1
  2. package/skills/automation-sandbox-post-copy-config-generate/SKILL.md +239 -0
  3. package/skills/automation-sandbox-post-copy-config-generate/assets/config_template.json +21 -0
  4. package/skills/automation-sandbox-post-copy-config-generate/assets/json_schema.json +90 -0
  5. package/skills/automation-sandbox-post-copy-config-generate/examples/sample_sop_excerpt.md +31 -0
  6. package/skills/automation-sandbox-post-copy-config-generate/examples/sample_sop_to_config.json +50 -0
  7. package/skills/automation-sandbox-post-copy-config-generate/references/configuration_catalog.md +76 -0
  8. package/skills/automation-sandbox-post-copy-config-generate/references/sop_parsing_patterns.md +157 -0
  9. package/skills/automation-sandbox-post-copy-config-generate/references/source_format_handling.md +230 -0
  10. package/skills/dx-apexguru-scan/SKILL.md +403 -0
  11. package/skills/dx-apexguru-scan/examples/README.md +54 -0
  12. package/skills/dx-apexguru-scan/examples/sample-decoded-summary.json +176 -0
  13. package/skills/dx-apexguru-scan/examples/sample-full-no-runtime-response.json +26 -0
  14. package/skills/dx-apexguru-scan/examples/sample-succeeded-response.json +15 -0
  15. package/skills/dx-apexguru-scan/references/api-reference.md +81 -0
  16. package/skills/dx-apexguru-scan/references/authentication.md +134 -0
  17. package/skills/dx-apexguru-scan/references/error-handling.md +56 -0
  18. package/skills/dx-apexguru-scan/references/violation-catalog.md +28 -0
  19. package/skills/dx-apexguru-scan/scripts/build-zip.sh +87 -0
  20. package/skills/dx-apexguru-scan/scripts/decode-report.js +389 -0
  21. package/skills/dx-apexguru-scan/scripts/resolve-token.sh +151 -0
  22. package/skills/dx-apexguru-scan/scripts/run-scan.sh +153 -0
  23. package/skills/dx-apexguru-scan/scripts/scan.sh +96 -0
  24. package/skills/dx-apexguru-scan/scripts/validate-token.js +121 -0
  25. package/skills/dx-devops-pipeline-manage/SKILL.md +263 -0
  26. package/skills/dx-devops-pipeline-manage/examples/common-workflows.md +177 -0
  27. package/skills/dx-devops-pipeline-manage/references/cli-commands.md +298 -0
  28. package/skills/dx-devops-pipeline-manage/references/parsing-patterns.md +134 -0
  29. package/skills/dx-devops-pipeline-manage/scripts/check-activation-ready.sh +34 -0
  30. package/skills/dx-devops-pipeline-manage/scripts/validate-org-type.sh +17 -0
  31. package/skills/dx-devops-pipeline-manage/scripts/verify-operation.sh +82 -0
  32. package/skills/dx-devops-promote/SKILL.md +214 -0
  33. package/skills/dx-devops-promote/examples/promotion-workflows.md +212 -0
  34. package/skills/dx-devops-promote/references/cli-commands.md +303 -0
  35. package/skills/experience-lwc-base-components-integrate/SKILL.md +176 -0
  36. package/skills/experience-lwc-base-components-integrate/references/lbc-expert-guidance.md +127 -0
  37. package/skills/experience-lwc-base-components-integrate/references/lightning-component-index.md +179 -0
  38. package/skills/experience-lwc-base-components-integrate/references/lightning-components.md +5429 -0
  39. package/skills/experience-lwc-base-components-integrate/scripts/extract-component-docs.sh +61 -0
  40. package/skills/experience-lwc-rtl-validate/SKILL.md +149 -0
  41. package/skills/experience-lwc-rtl-validate/references/rtl-expert.md +892 -0
  42. package/skills/experience-lwc-rtl-validate/scripts/scan-rtl-css.sh +206 -0
  43. package/skills/experience-lwc-typescript-migrate/SKILL.md +207 -0
  44. package/skills/experience-lwc-typescript-migrate/assets/dts-template.ts +15 -0
  45. package/skills/experience-lwc-typescript-migrate/assets/type-patterns.ts +44 -0
  46. package/skills/experience-lwc-typescript-migrate/scripts/find-consumers.sh +128 -0
  47. package/skills/experience-ui-bundle-localize/SKILL.md +323 -0
  48. package/skills/experience-ui-bundle-localize/references/gotchas.md +249 -0
  49. package/skills/experience-ui-bundle-localize/references/i18n-setup.md +169 -0
  50. package/skills/experience-ui-bundle-localize/references/interpolation.md +311 -0
  51. package/skills/experience-ui-bundle-localize/references/label-xml.md +282 -0
  52. package/skills/experience-ui-bundle-localize/references/verifying.md +219 -0
  53. package/skills/experience-ui-bundle-localize/scripts/check-i18n-wired.sh +195 -0
  54. package/skills/experience-ui-bundle-localize/scripts/check-manifest-registered.sh +100 -0
  55. package/skills/experience-ui-bundle-localize/scripts/check-org-api-version.sh +40 -0
  56. package/skills/experience-ui-bundle-localize/scripts/detect-bundle-type.sh +57 -0
  57. package/skills/platform-custom-lightning-type-generate/SKILL.md +3 -0
  58. package/skills/platform-custom-lightning-type-generate/assets/primitive-types-and-constraints.md +1 -1
  59. package/skills/platform-mcp-tool-widget-coordinate/SKILL.md +250 -0
  60. package/skills/platform-mcp-tool-widget-coordinate/examples/action-name-source-prompt.md +74 -0
  61. package/skills/platform-mcp-tool-widget-coordinate/examples/apex-invocable-source-prompt.md +90 -0
  62. package/skills/platform-mcp-tool-widget-coordinate/examples/nested-object-source-prompt.md +191 -0
  63. package/skills/platform-mcp-tool-widget-coordinate/examples/pasted-tool-output-prompt.md +85 -0
  64. package/skills/platform-mcp-tool-widget-coordinate/references/build-plan-format.md +74 -0
  65. package/skills/platform-mcp-tool-widget-coordinate/references/mcp-tool-output-discovery.md +184 -0
  66. package/skills/platform-mcp-tool-widget-coordinate/references/two-clt-modeling.md +128 -0
  67. package/skills/platform-mcp-tool-widget-coordinate/references/validation-gates.md +181 -0
@@ -0,0 +1,26 @@
1
+ {
2
+ "scanId": "255f5ecb-d967-47ad-9ca3-864d21bb425c",
3
+ "status": "SUCCEEDED",
4
+ "analysisMode": "full",
5
+ "report": "W3sicnVsZSI6ICJTY2hlbWFHZXRHbG9iYWxEZXNjcmliZU5vdEVmZmljaWVudCIsICJtZXNzYWdlIjogIkF2b2lkIHVzaW5nIFNjaGVtYS5nZXRHbG9iYWxEZXNjcmliZSgpIGluIEFwZXguIFRoaXMgbWV0aG9kIGNhdXNlcyB1bm5lY2Vzc2FyeSBvdmVyaGVhZCwgZGVjcmVhc2VzIHBlcmZvcm1hbmNlLCBhbmQgaW5jcmVhc2VzIHRoZSBsYXRlbmN5IG9mIHRoZSBhc3NvY2lhdGVkIGVudHJ5IHBvaW50LiIsICJsb2NhdGlvbnMiOiBbeyJzdGFydExpbmUiOiAyOCwgImNvbW1lbnQiOiAiU21hbGxBbnRpUGF0dGVybnMuYWNjb3VudFR5cGUiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn1dLCAicHJpbWFyeUxvY2F0aW9uSW5kZXgiOiAwLCAicmVzb3VyY2VzIjogWyJodHRwczovL2hlbHAuc2FsZXNmb3JjZS5jb20vcy9hcnRpY2xlVmlldz9pZD14Y2xvdWQuYXBleGd1cnVfYW50aXBhdHRlcm5fc2NoZW1hX2dldGdsb2JhbGRlc2NyaWJlX25vdF9lZmZpY2llbnQuaHRtJnR5cGU9NSJdLCAic2V2ZXJpdHkiOiA0LCAic3VnZ2VzdGlvbnMiOiBbeyJtZXNzYWdlIjogIiAgICAgICAgcmV0dXJuIEFjY291bnQuc09iamVjdFR5cGU7IiwgImxvY2F0aW9uIjogeyJzdGFydExpbmUiOiAyOCwgImNvbW1lbnQiOiAiU21hbGxBbnRpUGF0dGVybnMuYWNjb3VudFR5cGUiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn19XSwgIm1ldGFkYXRhIjogeyJvcmlnaW5hbF9jb2RlIjogIiAgICAgICAgcmV0dXJuIFNjaGVtYS5nZXRHbG9iYWxEZXNjcmliZSgpLmdldCgnQWNjb3VudCcpOyIsICJjbGFzc19uYW1lIjogIlNtYWxsQW50aVBhdHRlcm5zIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyJ9fSwgeyJydWxlIjogIlNvcWxJbkFMb29wIiwgIm1lc3NhZ2UiOiAiWW91J3JlIGNhbGxpbmcgYW4gZXhwZW5zaXZlIFNPUUwgaW4gYSBsb29wLCB3aGljaCBjYW4gY2F1c2UgcGVyZm9ybWFuY2UgaXNzdWVzLiBPcHRpbWl6ZSB5b3VyIFNPUUwgdG8gY2FsbCBvbmNlIGFuZCByZXVzZSB0aGUgcmV0dXJuIHZhbHVlLiIsICJsb2NhdGlvbnMiOiBbeyJzdGFydExpbmUiOiA0LCAiY29tbWVudCI6ICJTbWFsbEFudGlQYXR0ZXJucy5zb3FsSW5Mb29wIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyJ9XSwgInByaW1hcnlMb2NhdGlvbkluZGV4IjogMCwgInJlc291cmNlcyI6IFsiaHR0cHM6Ly9oZWxwLnNhbGVzZm9yY2UuY29tL3MvYXJ0aWNsZVZpZXc/aWQ9eGNsb3VkLmFwZXhndXJ1X2FudGlwYXR0ZXJuX3NvcWxfaW5fbG9vcC5odG0mdHlwZT01Il0sICJzZXZlcml0eSI6IDQsICJzdWdnZXN0aW9ucyI6IFt7Im1lc3NhZ2UiOiAicHVibGljIHN0YXRpYyB2b2lkIHNvcWxJbkxvb3AoTGlzdDxBY2NvdW50PiBhY2NvdW50cykge1xuICAgIFNldDxJZD4gYWNjb3VudElkcyA9IG5ldyBTZXQ8SWQ+KCk7XG4gICAgZm9yIChBY2NvdW50IGFjYyA6IGFjY291bnRzKSB7XG4gICAgICAgIGFjY291bnRJZHMuYWRkKGFjYy5JZCk7XG4gICAgfVxuICAgIE1hcDxJZCwgTGlzdDxDb250YWN0Pj4gY29udGFjdHNCeUFjY291bnRJZCA9IG5ldyBNYXA8SWQsIExpc3Q8Q29udGFjdD4+KCk7XG4gICAgZm9yIChDb250YWN0IGMgOiBbU0VMRUNUIElkLCBOYW1lIEZST00gQ29udGFjdCBXSEVSRSBBY2NvdW50SWQgSU4gOmFjY291bnRJZHNdKSB7XG4gICAgICAgIGlmICghY29udGFjdHNCeUFjY291bnRJZC5jb250YWluc0tleShjLkFjY291bnRJZCkpIHtcbiAgICAgICAgICAgIGNvbnRhY3RzQnlBY2NvdW50SWQucHV0KGMuQWNjb3VudElkLCBuZXcgTGlzdDxDb250YWN0PigpKTtcbiAgICAgICAgfVxuICAgICAgICBjb250YWN0c0J5QWNjb3VudElkLmdldChjLkFjY291bnRJZCkuYWRkKGMpO1xuICAgIH1cbiAgICBmb3IgKEFjY291bnQgYWNjIDogYWNjb3VudHMpIHtcbiAgICAgICAgTGlzdDxDb250YWN0PiBjb250YWN0cyA9IGNvbnRhY3RzQnlBY2NvdW50SWQuY29udGFpbnNLZXkoYWNjLklkKSA/IGNvbnRhY3RzQnlBY2NvdW50SWQuZ2V0KGFjYy5JZCkgOiBuZXcgTGlzdDxDb250YWN0PigpO1xuICAgICAgICBTeXN0ZW0uZGVidWcoY29udGFjdHMuc2l6ZSgpKTtcbiAgICB9XG59IiwgImxvY2F0aW9uIjogeyJzdGFydExpbmUiOiA0LCAiY29tbWVudCI6ICJTbWFsbEFudGlQYXR0ZXJucy5zb3FsSW5Mb29wIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyJ9fV0sICJtZXRhZGF0YSI6IHsib3JpZ2luYWxfY29kZSI6ICJMaW5lIDI6XG5MaW5lIDM6ICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBzb3FsSW5Mb29wKExpc3Q8QWNjb3VudD4gYWNjb3VudHMpIHtcbkxpbmUgNDogICAgICAgIGZvciAoQWNjb3VudCBhY2MgOiBhY2NvdW50cykge1xuTGluZSA1OiAgICAgICAgICAgIExpc3Q8Q29udGFjdD4gY29udGFjdHMgPSBbU0VMRUNUIElkLCBOYW1lIEZST00gQ29udGFjdCBXSEVSRSBBY2NvdW50SWQgPSA6YWNjLklkXTtcbkxpbmUgNjogICAgICAgICAgICBTeXN0ZW0uZGVidWcoY29udGFjdHMuc2l6ZSgpKTtcbkxpbmUgNzogICAgICAgIH1cbiIsICJjbGFzc19uYW1lIjogIlNtYWxsQW50aVBhdHRlcm5zIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyIsICJjYXRlZ29yeSI6ICJzb3FsX2luX2xvb3AifX0sIHsicnVsZSI6ICJTb3FsSW5BTG9vcE9uZUhvcCIsICJtZXNzYWdlIjogIllvdSdyZSBjYWxsaW5nIGEgbWV0aG9kIHRoYXQgY29udGFpbnMgYW4gU09RTCBxdWVyeSB3aXRoaW4gYSBsb29wLiBUbyBhdm9pZCBib3R0bGVuZWNrcyBhbmQgc3RheSB3aXRoaW4gZ292ZXJub3IgbGltaXRzLCBtb3ZlIFNPUUwgcXVlcmllcyBvdXRzaWRlIG9mIGxvb3BzLiIsICJsb2NhdGlvbnMiOiBbeyJzdGFydExpbmUiOiA1MSwgImNvbW1lbnQiOiAiU21hbGxBbnRpUGF0dGVybnMubm90aWZ5T3duZXJzIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyJ9LCB7InN0YXJ0TGluZSI6IDU4LCAiY29tbWVudCI6ICJTT1FMIGNhbGwgaW46IFNtYWxsQW50aVBhdHRlcm5zLmdldENhc2VCeUlkIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyJ9XSwgInByaW1hcnlMb2NhdGlvbkluZGV4IjogMCwgInJlc291cmNlcyI6IFsiaHR0cHM6Ly9oZWxwLnNhbGVzZm9yY2UuY29tL3MvYXJ0aWNsZVZpZXc/aWQ9eGNsb3VkLmFwZXhndXJ1X2FudGlwYXR0ZXJuX3NvcWxfaW5fbG9vcF9vbmVfaG9wLmh0bSZ0eXBlPTUiXSwgInNldmVyaXR5IjogNCwgIm1ldGFkYXRhIjogeyJvcmlnaW5hbF9jb2RlIjogIkxpbmUgNDk6XG5MaW5lIDUwOiAgICBwdWJsaWMgc3RhdGljIHZvaWQgbm90aWZ5T3duZXJzKExpc3Q8SWQ+IGNhc2VJZHMpIHtcbkxpbmUgNTE6ICAgICAgICBmb3IgKElkIGNhc2VJZCA6IGNhc2VJZHMpIHtcbkxpbmUgNTI6ICAgICAgICAgICAgQ2FzZSBjID0gZ2V0Q2FzZUJ5SWQoY2FzZUlkKTtcbkxpbmUgNTM6ICAgICAgICAgICAgU3lzdGVtLmRlYnVnKCdPd25lcjogJyArIGMuT3duZXJJZCk7XG5MaW5lIDU0OiAgICAgICAgfVxuIiwgImNsYXNzX25hbWUiOiAiU21hbGxBbnRpUGF0dGVybnMiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIiwgImNhdGVnb3J5IjogInNvcWxfaW5fbG9vcF9ob3AifX0sIHsicnVsZSI6ICJEbWxJbkFMb29wIiwgIm1lc3NhZ2UiOiAiWW91J3JlIGNhbGxpbmcgYW4gZXhwZW5zaXZlIERNTCBpbiBhIGxvb3AsIHdoaWNoIGNhbiBjYXVzZSBwZXJmb3JtYW5jZSBpc3N1ZXMuIE9wdGltaXplIHlvdXIgRE1MIHN0YXRlbWVudCB0byBjYWxsIG9uY2UuIiwgImxvY2F0aW9ucyI6IFt7InN0YXJ0TGluZSI6IDEzLCAiY29tbWVudCI6ICJTbWFsbEFudGlQYXR0ZXJucy5kbWxJbkxvb3AiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn1dLCAicHJpbWFyeUxvY2F0aW9uSW5kZXgiOiAwLCAicmVzb3VyY2VzIjogWyJodHRwczovL2hlbHAuc2FsZXNmb3JjZS5jb20vcy9hcnRpY2xlVmlldz9pZD14Y2xvdWQuYXBleGd1cnVfYW50aXBhdHRlcm5fZG1sX2luX2xvb3AuaHRtJnR5cGU9NSJdLCAic2V2ZXJpdHkiOiA0LCAic3VnZ2VzdGlvbnMiOiBbeyJtZXNzYWdlIjogInB1YmxpYyBzdGF0aWMgdm9pZCBkbWxJbkxvb3AoTGlzdDxDb250YWN0PiBjb250YWN0cykge1xuICAgIGZvciAoQ29udGFjdCBjIDogY29udGFjdHMpIHtcbiAgICAgICAgYy5EZXNjcmlwdGlvbiA9ICd0b3VjaGVkJztcbiAgICB9XG4gICAgaWYgKCFjb250YWN0cy5pc0VtcHR5KCkpIHtcbiAgICAgICAgdXBkYXRlIGNvbnRhY3RzO1xuICAgIH1cbn0iLCAibG9jYXRpb24iOiB7InN0YXJ0TGluZSI6IDEzLCAiY29tbWVudCI6ICJTbWFsbEFudGlQYXR0ZXJucy5kbWxJbkxvb3AiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn19XSwgIm1ldGFkYXRhIjogeyJvcmlnaW5hbF9jb2RlIjogIkxpbmUgMTI6ICAgICAgICAgICAgYy5EZXNjcmlwdGlvbiA9ICd0b3VjaGVkJztcbkxpbmUgMTM6ICAgICAgICAgICAgdXBkYXRlIGM7XG5MaW5lIDE0OiAgICAgICAgfVxuIiwgImNsYXNzX25hbWUiOiAiU21hbGxBbnRpUGF0dGVybnMiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIiwgImNhdGVnb3J5IjogImRtbF9pbl9sb29wIn19LCB7InJ1bGUiOiAiU29xbFdpdGhOZWdhdGl2ZUV4cHJlc3Npb25zIiwgIm1lc3NhZ2UiOiAiQ2FsbGluZyBTT1FMIHdpdGggbmVnYXRpdmUgZXhwcmVzc2lvbnMgY2F1c2VzIHBlcmZvcm1hbmNlIGlzc3Vlcy4iLCAibG9jYXRpb25zIjogW3sic3RhcnRMaW5lIjogMzIsICJjb21tZW50IjogIlNtYWxsQW50aVBhdHRlcm5zLm5vblByb3NwZWN0aW5nT3BwcyIsICJmaWxlIjogImZvcmNlLWFwcC9tYWluL2RlZmF1bHQvY2xhc3Nlcy9TbWFsbEFudGlQYXR0ZXJucy5jbHMifV0sICJwcmltYXJ5TG9jYXRpb25JbmRleCI6IDAsICJyZXNvdXJjZXMiOiBbImh0dHBzOi8vaGVscC5zYWxlc2ZvcmNlLmNvbS9zL2FydGljbGVWaWV3P2lkPXhjbG91ZC5hcGV4Z3VydV9hbnRpcGF0dGVybl9zb3FsX3dpdGhfbmVnYXRpdmVfZXhwcmVzc2lvbnMuaHRtJnR5cGU9NSJdLCAic2V2ZXJpdHkiOiA0LCAibWV0YWRhdGEiOiB7Im9yaWdpbmFsX2NvZGUiOiAiW1NFTEVDVCBJZCwgTmFtZSwgU3RhZ2VOYW1lIEZST00gT3Bwb3J0dW5pdHkgV0hFUkUgU3RhZ2VOYW1lICE9ICdQcm9zcGVjdGluZyddIiwgImNsYXNzX25hbWUiOiAiU21hbGxBbnRpUGF0dGVybnMiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIiwgImNhdGVnb3J5IjogInNvcWxfd2l0aF9uZWdhdGl2ZV9leHByZXNzaW9ucyJ9fSwgeyJydWxlIjogIlNvcWxXaXRob3V0QVdoZXJlQ2xhdXNlT3JMaW1pdFN0YXRlbWVudCIsICJtZXNzYWdlIjogIkNhbGxpbmcgU09RTCB3aXRob3V0IGEgV0hFUkUgY2xhdXNlIG9yIExJTUlUIHN0YXRlbWVudCBjYXVzZXMgcGVyZm9ybWFuY2UgaXNzdWVzLiIsICJsb2NhdGlvbnMiOiBbeyJzdGFydExpbmUiOiAxOCwgImNvbW1lbnQiOiAiU21hbGxBbnRpUGF0dGVybnMuYWxsT3BwcyIsICJmaWxlIjogImZvcmNlLWFwcC9tYWluL2RlZmF1bHQvY2xhc3Nlcy9TbWFsbEFudGlQYXR0ZXJucy5jbHMifV0sICJwcmltYXJ5TG9jYXRpb25JbmRleCI6IDAsICJyZXNvdXJjZXMiOiBbImh0dHBzOi8vaGVscC5zYWxlc2ZvcmNlLmNvbS9zL2FydGljbGVWaWV3P2lkPXhjbG91ZC5hcGV4Z3VydV9hbnRpcGF0dGVybl9zb3FsX3dpdGhvdXRfd2hlcmVfY2xhdXNlX29yX2xpbWl0X3N0YXRlbWVudC5odG0mdHlwZT01Il0sICJzZXZlcml0eSI6IDQsICJtZXRhZGF0YSI6IHsib3JpZ2luYWxfY29kZSI6ICJbU0VMRUNUIElkLCBOYW1lLCBBbW91bnQsIFN0YWdlTmFtZSBGUk9NIE9wcG9ydHVuaXR5XSIsICJjbGFzc19uYW1lIjogIlNtYWxsQW50aVBhdHRlcm5zIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyIsICJjYXRlZ29yeSI6ICJzb3FsX3dpdGhvdXRfd2hlcmVfY2xhdXNlX29yX2xpbWl0X3N0YXRlbWVudCJ9fSwgeyJydWxlIjogIlNvcWxXaXRob3V0QVdoZXJlQ2xhdXNlT3JMaW1pdFN0YXRlbWVudCIsICJtZXNzYWdlIjogIkNhbGxpbmcgU09RTCB3aXRob3V0IGEgV0hFUkUgY2xhdXNlIG9yIExJTUlUIHN0YXRlbWVudCBjYXVzZXMgcGVyZm9ybWFuY2UgaXNzdWVzLiIsICJsb2NhdGlvbnMiOiBbeyJzdGFydExpbmUiOiA3NCwgImNvbW1lbnQiOiAiU21hbGxBbnRpUGF0dGVybnMuc29ydGVkQ29udGFjdHNCeU5hbWUiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn1dLCAicHJpbWFyeUxvY2F0aW9uSW5kZXgiOiAwLCAicmVzb3VyY2VzIjogWyJodHRwczovL2hlbHAuc2FsZXNmb3JjZS5jb20vcy9hcnRpY2xlVmlldz9pZD14Y2xvdWQuYXBleGd1cnVfYW50aXBhdHRlcm5fc29xbF93aXRob3V0X3doZXJlX2NsYXVzZV9vcl9saW1pdF9zdGF0ZW1lbnQuaHRtJnR5cGU9NSJdLCAic2V2ZXJpdHkiOiA0LCAibWV0YWRhdGEiOiB7Im9yaWdpbmFsX2NvZGUiOiAiW1NFTEVDVCBJZCwgTmFtZSBGUk9NIENvbnRhY3RdIiwgImNsYXNzX25hbWUiOiAiU21hbGxBbnRpUGF0dGVybnMiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIiwgImNhdGVnb3J5IjogInNvcWxfd2l0aG91dF93aGVyZV9jbGF1c2Vfb3JfbGltaXRfc3RhdGVtZW50In19LCB7InJ1bGUiOiAiU29xbFdpdGhvdXRBV2hlcmVDbGF1c2VPckxpbWl0U3RhdGVtZW50IiwgIm1lc3NhZ2UiOiAiQ2FsbGluZyBTT1FMIHdpdGhvdXQgYSBXSEVSRSBjbGF1c2Ugb3IgTElNSVQgc3RhdGVtZW50IGNhdXNlcyBwZXJmb3JtYW5jZSBpc3N1ZXMuIiwgImxvY2F0aW9ucyI6IFt7InN0YXJ0TGluZSI6IDgxLCAiY29tbWVudCI6ICJTbWFsbEFudGlQYXR0ZXJucy5hY2NvdW50c0J5SWQiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn1dLCAicHJpbWFyeUxvY2F0aW9uSW5kZXgiOiAwLCAicmVzb3VyY2VzIjogWyJodHRwczovL2hlbHAuc2FsZXNmb3JjZS5jb20vcy9hcnRpY2xlVmlldz9pZD14Y2xvdWQuYXBleGd1cnVfYW50aXBhdHRlcm5fc29xbF93aXRob3V0X3doZXJlX2NsYXVzZV9vcl9saW1pdF9zdGF0ZW1lbnQuaHRtJnR5cGU9NSJdLCAic2V2ZXJpdHkiOiA0LCAibWV0YWRhdGEiOiB7Im9yaWdpbmFsX2NvZGUiOiAiW1NFTEVDVCBJZCwgTmFtZSBGUk9NIEFjY291bnRdIiwgImNsYXNzX25hbWUiOiAiU21hbGxBbnRpUGF0dGVybnMiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIiwgImNhdGVnb3J5IjogInNvcWxfd2l0aG91dF93aGVyZV9jbGF1c2Vfb3JfbGltaXRfc3RhdGVtZW50In19LCB7InJ1bGUiOiAiU29xbCBBZ2dyZWdhdGlvbiIsICJtZXNzYWdlIjogIllvdSdyZSB1c2luZyBsb29wcyB0byBtYW51YWxseSBjb21wdXRlIHZhbHVlcywgd2hpY2ggY2F1c2VzIHBlcmZvcm1hbmNlIGlzc3VlcywgYW5kIGNhbiBleGNlZWQgZ292ZXJub3IgbGltaXRzLiBJbnN0ZWFkLCB1c2UgQXBleCBhZ2dyZWdhdGUgZnVuY3Rpb25zIGxpa2UgU1VNIGFuZCBDT1VOVC4iLCAibG9jYXRpb25zIjogW3sic3RhcnRMaW5lIjogMzYsICJjb21tZW50IjogIlNtYWxsQW50aVBhdHRlcm5zLnRvdGFsT3BlbkFtb3VudCIsICJmaWxlIjogImZvcmNlLWFwcC9tYWluL2RlZmF1bHQvY2xhc3Nlcy9TbWFsbEFudGlQYXR0ZXJucy5jbHMifV0sICJwcmltYXJ5TG9jYXRpb25JbmRleCI6IDAsICJyZXNvdXJjZXMiOiBbImh0dHBzOi8vaGVscC5zYWxlc2ZvcmNlLmNvbS9zL2FydGljbGVWaWV3P2lkPXhjbG91ZC5hcGV4Z3VydV9hbnRpcGF0dGVybl9hZ2dyZWdhdGluZ19pbl9hcGV4Lmh0bSZ0eXBlPTUiXSwgInNldmVyaXR5IjogNCwgInN1Z2dlc3Rpb25zIjogW3sibWVzc2FnZSI6ICJBZ2dyZWdhdGVSZXN1bHQgYXIgPSBbU0VMRUNUIFNVTShBbW91bnQpIHRvdGFsIEZST00gT3Bwb3J0dW5pdHkgV0hFUkUgQWNjb3VudElkID0gOmFjY291bnRJZCBBTkQgSXNDbG9zZWQgPSBmYWxzZV07XG5EZWNpbWFsIHRvdGFsID0gKERlY2ltYWwpYXIuZ2V0KCd0b3RhbCcpOyIsICJsb2NhdGlvbiI6IHsic3RhcnRMaW5lIjogMzYsICJjb21tZW50IjogIlNtYWxsQW50aVBhdHRlcm5zLnRvdGFsT3BlbkFtb3VudCIsICJmaWxlIjogImZvcmNlLWFwcC9tYWluL2RlZmF1bHQvY2xhc3Nlcy9TbWFsbEFudGlQYXR0ZXJucy5jbHMifX1dLCAibWV0YWRhdGEiOiB7Im9yaWdpbmFsX2NvZGUiOiAiICAgICAgICAgICAgIFNFTEVDVCBBbW91bnQgRlJPTSBPcHBvcnR1bml0eSBXSEVSRSBBY2NvdW50SWQgPSA6YWNjb3VudElkIEFORCBJc0Nsb3NlZCA9IGZhbHNlICAgICAgICAgIiwgImNsYXNzX25hbWUiOiAiU21hbGxBbnRpUGF0dGVybnMiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIiwgImNhdGVnb3J5IjogInJlY29yZF9hZ2dyZWdhdGlvbl9pbl9hcGV4In19LCB7InJ1bGUiOiAiU29xbCBBZ2dyZWdhdGlvbiIsICJtZXNzYWdlIjogIllvdSdyZSB1c2luZyBsb29wcyB0byBtYW51YWxseSBjb21wdXRlIHZhbHVlcywgd2hpY2ggY2F1c2VzIHBlcmZvcm1hbmNlIGlzc3VlcywgYW5kIGNhbiBleGNlZWQgZ292ZXJub3IgbGltaXRzLiBJbnN0ZWFkLCB1c2UgQXBleCBhZ2dyZWdhdGUgZnVuY3Rpb25zIGxpa2UgU1VNIGFuZCBDT1VOVC4iLCAibG9jYXRpb25zIjogW3sic3RhcnRMaW5lIjogOTcsICJjb21tZW50IjogIlNtYWxsQW50aVBhdHRlcm5zLnN1bU9wZW5PcHBBbW91bnRzIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyJ9XSwgInByaW1hcnlMb2NhdGlvbkluZGV4IjogMCwgInJlc291cmNlcyI6IFsiaHR0cHM6Ly9oZWxwLnNhbGVzZm9yY2UuY29tL3MvYXJ0aWNsZVZpZXc/aWQ9eGNsb3VkLmFwZXhndXJ1X2FudGlwYXR0ZXJuX2FnZ3JlZ2F0aW5nX2luX2FwZXguaHRtJnR5cGU9NSJdLCAic2V2ZXJpdHkiOiA0LCAic3VnZ2VzdGlvbnMiOiBbeyJtZXNzYWdlIjogIkFnZ3JlZ2F0ZVJlc3VsdCBhciA9IFtTRUxFQ1QgU1VNKEFtb3VudCkgdG90YWwgRlJPTSBPcHBvcnR1bml0eSBXSEVSRSBBY2NvdW50SWQgPSA6YWNjb3VudElkIEFORCBJc0Nsb3NlZCA9IGZhbHNlXTtcbkRlY2ltYWwgdG90YWwgPSAoRGVjaW1hbClhci5nZXQoJ3RvdGFsJyk7IiwgImxvY2F0aW9uIjogeyJzdGFydExpbmUiOiA5NywgImNvbW1lbnQiOiAiU21hbGxBbnRpUGF0dGVybnMuc3VtT3Blbk9wcEFtb3VudHMiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn19XSwgIm1ldGFkYXRhIjogeyJvcmlnaW5hbF9jb2RlIjogIlNFTEVDVCBBbW91bnQgRlJPTSBPcHBvcnR1bml0eSBXSEVSRSBBY2NvdW50SWQgPSA6YWNjb3VudElkIEFORCBJc0Nsb3NlZCA9IGZhbHNlIiwgImNsYXNzX25hbWUiOiAiU21hbGxBbnRpUGF0dGVybnMiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIiwgImNhdGVnb3J5IjogInJlY29yZF9hZ2dyZWdhdGlvbl9pbl9hcGV4In19LCB7InJ1bGUiOiAiU29xbFdpdGhBcGV4RmlsdGVyIiwgIm1lc3NhZ2UiOiAiQ2FsbGluZyBTT1FMIHdpdGhvdXQgYSBXSEVSRSBjbGF1c2Ugb3IgTElNSVQgc3RhdGVtZW50IHJldHJpZXZlcyBhbGwgcmVjb3JkcywgY2F1c2VzIHBlcmZvcm1hbmNlIGlzc3VlcywgYW5kIGNhbiBleGNlZWQgZ292ZXJub3IgbGltaXRzLiIsICJsb2NhdGlvbnMiOiBbeyJzdGFydExpbmUiOiA2NiwgImNvbW1lbnQiOiAiU21hbGxBbnRpUGF0dGVybnMucHJvY2Vzc0hpZ2hWYWx1ZU9wcHMiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn1dLCAicHJpbWFyeUxvY2F0aW9uSW5kZXgiOiAwLCAicmVzb3VyY2VzIjogWyJodHRwczovL2hlbHAuc2FsZXNmb3JjZS5jb20vcy9hcnRpY2xlVmlldz9pZD14Y2xvdWQuYXBleGd1cnVfYW50aXBhdHRlcm5fc29xbF93aXRoX2FwZXhfZmlsdGVyLmh0bSZ0eXBlPTUiXSwgInNldmVyaXR5IjogNCwgInN1Z2dlc3Rpb25zIjogW3sibWVzc2FnZSI6ICJTRUxFQ1QgSWQsIE5hbWUsIEFtb3VudCwgU3RhZ2VOYW1lIEZST00gT3Bwb3J0dW5pdHkgV0hFUkUgQW1vdW50ICE9IE5VTEwgQU5EIEFtb3VudCA+PSAxMDAwMCIsICJsb2NhdGlvbiI6IHsic3RhcnRMaW5lIjogNjYsICJjb21tZW50IjogIlNtYWxsQW50aVBhdHRlcm5zLnByb2Nlc3NIaWdoVmFsdWVPcHBzIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyJ9fV0sICJtZXRhZGF0YSI6IHsib3JpZ2luYWxfY29kZSI6ICJTRUxFQ1QgSWQsIE5hbWUsIEFtb3VudCwgU3RhZ2VOYW1lIEZST00gT3Bwb3J0dW5pdHkiLCAiY2xhc3NfbmFtZSI6ICJTbWFsbEFudGlQYXR0ZXJucyIsICJmaWxlIjogImZvcmNlLWFwcC9tYWluL2RlZmF1bHQvY2xhc3Nlcy9TbWFsbEFudGlQYXR0ZXJucy5jbHMiLCAiY2F0ZWdvcnkiOiAicmVjb3JkX2ZpbHRlcmluZ19pbl9hcGV4In19LCB7InJ1bGUiOiAiU29ydGluZ0luQXBleCIsICJtZXNzYWdlIjogIllvdXIgU09RTCBxdWVyeSByZXRyaWV2ZXMgcmVjb3JkcyBpbiBhbiB1bnNvcnRlZCBvcmRlci4gVGhpcyB3YXN0ZXMgQ1BVIHRpbWUgYW5kIGNhbiBleGNlZWQgZ292ZXJub3IgbGltaXRzLiBVc2UgdGhlIE9SREVSIEJZIGNsYXVzZSB0byBlZmZpY2llbnRseSBzb3J0IGFuZCByZXRyaWV2ZSByZWNvcmRzLiIsICJsb2NhdGlvbnMiOiBbeyJzdGFydExpbmUiOiA3NCwgImNvbW1lbnQiOiAiU21hbGxBbnRpUGF0dGVybnMuc29ydGVkQ29udGFjdHNCeU5hbWUiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn1dLCAicHJpbWFyeUxvY2F0aW9uSW5kZXgiOiAwLCAicmVzb3VyY2VzIjogWyJodHRwczovL2hlbHAuc2FsZXNmb3JjZS5jb20vcy9hcnRpY2xlVmlldz9pZD14Y2xvdWQuYXBleGd1cnVfYW50aXBhdHRlcm5fc29ydGluZ19pbl9hcGV4Lmh0bSZ0eXBlPTUiXSwgInNldmVyaXR5IjogNCwgInN1Z2dlc3Rpb25zIjogW3sibWVzc2FnZSI6ICIgICAgICAgIExpc3Q8Q29udGFjdD4gY29udGFjdExpc3QgPSBbU0VMRUNUIElkLCBOYW1lIEZST00gQ29udGFjdCBPUkRFUiBCWSBOYW1lXTtcbi8vICAgICAgICAgY29udGFjdExpc3Quc29ydCgpOyIsICJsb2NhdGlvbiI6IHsic3RhcnRMaW5lIjogNzQsICJjb21tZW50IjogIlNtYWxsQW50aVBhdHRlcm5zLnNvcnRlZENvbnRhY3RzQnlOYW1lIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyJ9fV0sICJtZXRhZGF0YSI6IHsib3JpZ2luYWxfY29kZSI6ICIgICAgICAgIExpc3Q8Q29udGFjdD4gY29udGFjdExpc3QgPSBbU0VMRUNUIElkLCBOYW1lIEZST00gQ29udGFjdF07XG4gICAgICAgIGNvbnRhY3RMaXN0LnNvcnQoKTtcbiIsICJjbGFzc19uYW1lIjogIlNtYWxsQW50aVBhdHRlcm5zIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyIsICJjYXRlZ29yeSI6ICJyZWNvcmRfc29ydGluZ19pbl9hcGV4In19LCB7InJ1bGUiOiAiU29xbFdpdGhVbnVzZWRGaWVsZHMiLCAibWVzc2FnZSI6ICJZb3UncmUgcmV0cmlldmluZyB0aGUgdW51c2VkIGZpZWxkIE5hbWUgaW4gYW4gU09RTCBxdWVyeS4gVG8gYXZvaWQgaW5jcmVhc2luZyByZXNvdXJjZSBjb25zdW1wdGlvbiBhbmQgcXVlcnkgdGltZSwgc2VsZWN0IG9ubHkgdGhlIG5lY2Vzc2FyeSBmaWVsZHMuIiwgImxvY2F0aW9ucyI6IFt7InN0YXJ0TGluZSI6IDUsICJjb21tZW50IjogIlNtYWxsQW50aVBhdHRlcm5zLnNvcWxJbkxvb3AiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn1dLCAicHJpbWFyeUxvY2F0aW9uSW5kZXgiOiAwLCAicmVzb3VyY2VzIjogWyJodHRwczovL2hlbHAuc2FsZXNmb3JjZS5jb20vcy9hcnRpY2xlVmlldz9pZD14Y2xvdWQuYXBleGd1cnVfYW50aXBhdHRlcm5fc29xbF93aXRoX3VudXNlZF9maWVsZHMuaHRtJnR5cGU9NSJdLCAic2V2ZXJpdHkiOiA0LCAic3VnZ2VzdGlvbnMiOiBbeyJtZXNzYWdlIjogIlNFTEVDVCBJZCBGUk9NIENvbnRhY3QgV0hFUkUgQWNjb3VudElkID0gOmFjYy5JZCIsICJsb2NhdGlvbiI6IHsic3RhcnRMaW5lIjogNSwgImNvbW1lbnQiOiAiU21hbGxBbnRpUGF0dGVybnMuc29xbEluTG9vcCIsICJmaWxlIjogImZvcmNlLWFwcC9tYWluL2RlZmF1bHQvY2xhc3Nlcy9TbWFsbEFudGlQYXR0ZXJucy5jbHMifX1dLCAibWV0YWRhdGEiOiB7Im9yaWdpbmFsX2NvZGUiOiAiU0VMRUNUIElkLCBOYW1lIEZST00gQ29udGFjdCBXSEVSRSBBY2NvdW50SWQgPSA6YWNjLklkIiwgImNsYXNzX25hbWUiOiAiU21hbGxBbnRpUGF0dGVybnMiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIiwgImNhdGVnb3J5IjogInNvcWxfdW51c2VkX2ZpZWxkcyJ9fSwgeyJydWxlIjogIlNvcWxXaXRoVW51c2VkRmllbGRzIiwgIm1lc3NhZ2UiOiAiWW91J3JlIHJldHJpZXZpbmcgdGhlIHVudXNlZCBmaWVsZHMgVHlwZSwgSW5kdXN0cnksIFJhdGluZywgUGhvbmUsIFdlYnNpdGUgaW4gYW4gU09RTCBxdWVyeS4gVG8gYXZvaWQgaW5jcmVhc2luZyByZXNvdXJjZSBjb25zdW1wdGlvbiBhbmQgcXVlcnkgdGltZSwgc2VsZWN0IG9ubHkgdGhlIG5lY2Vzc2FyeSBmaWVsZHMuIiwgImxvY2F0aW9ucyI6IFt7InN0YXJ0TGluZSI6IDIyLCAiY29tbWVudCI6ICJTbWFsbEFudGlQYXR0ZXJucy5nZXRBY2NvdW50TmFtZSIsICJmaWxlIjogImZvcmNlLWFwcC9tYWluL2RlZmF1bHQvY2xhc3Nlcy9TbWFsbEFudGlQYXR0ZXJucy5jbHMifV0sICJwcmltYXJ5TG9jYXRpb25JbmRleCI6IDAsICJyZXNvdXJjZXMiOiBbImh0dHBzOi8vaGVscC5zYWxlc2ZvcmNlLmNvbS9zL2FydGljbGVWaWV3P2lkPXhjbG91ZC5hcGV4Z3VydV9hbnRpcGF0dGVybl9zb3FsX3dpdGhfdW51c2VkX2ZpZWxkcy5odG0mdHlwZT01Il0sICJzZXZlcml0eSI6IDQsICJzdWdnZXN0aW9ucyI6IFt7Im1lc3NhZ2UiOiAiU0VMRUNUIElkLCBOYW1lIEZST00gQWNjb3VudCBXSEVSRSBJZCA9IDphY2NvdW50SWQgTElNSVQgMSIsICJsb2NhdGlvbiI6IHsic3RhcnRMaW5lIjogMjIsICJjb21tZW50IjogIlNtYWxsQW50aVBhdHRlcm5zLmdldEFjY291bnROYW1lIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyJ9fV0sICJtZXRhZGF0YSI6IHsib3JpZ2luYWxfY29kZSI6ICJTRUxFQ1QgSWQsIE5hbWUsIFR5cGUsIEluZHVzdHJ5LCBSYXRpbmcsIFBob25lLCBXZWJzaXRlICAgICAgICAgICAgICAgICAgICAgIEZST00gQWNjb3VudCBXSEVSRSBJZCA9IDphY2NvdW50SWQgTElNSVQgMSIsICJjbGFzc19uYW1lIjogIlNtYWxsQW50aVBhdHRlcm5zIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyIsICJjYXRlZ29yeSI6ICJzb3FsX3VudXNlZF9maWVsZHMifX0sIHsicnVsZSI6ICJTb3FsV2l0aFVudXNlZEZpZWxkcyIsICJtZXNzYWdlIjogIllvdSdyZSByZXRyaWV2aW5nIHRoZSB1bnVzZWQgZmllbGQgU3RhZ2VOYW1lIGluIGFuIFNPUUwgcXVlcnkuIFRvIGF2b2lkIGluY3JlYXNpbmcgcmVzb3VyY2UgY29uc3VtcHRpb24gYW5kIHF1ZXJ5IHRpbWUsIHNlbGVjdCBvbmx5IHRoZSBuZWNlc3NhcnkgZmllbGRzLiIsICJsb2NhdGlvbnMiOiBbeyJzdGFydExpbmUiOiA2NiwgImNvbW1lbnQiOiAiU21hbGxBbnRpUGF0dGVybnMucHJvY2Vzc0hpZ2hWYWx1ZU9wcHMiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn1dLCAicHJpbWFyeUxvY2F0aW9uSW5kZXgiOiAwLCAicmVzb3VyY2VzIjogWyJodHRwczovL2hlbHAuc2FsZXNmb3JjZS5jb20vcy9hcnRpY2xlVmlldz9pZD14Y2xvdWQuYXBleGd1cnVfYW50aXBhdHRlcm5fc29xbF93aXRoX3VudXNlZF9maWVsZHMuaHRtJnR5cGU9NSJdLCAic2V2ZXJpdHkiOiA0LCAic3VnZ2VzdGlvbnMiOiBbeyJtZXNzYWdlIjogIlNFTEVDVCBJZCwgTmFtZSwgQW1vdW50IEZST00gT3Bwb3J0dW5pdHkiLCAibG9jYXRpb24iOiB7InN0YXJ0TGluZSI6IDY2LCAiY29tbWVudCI6ICJTbWFsbEFudGlQYXR0ZXJucy5wcm9jZXNzSGlnaFZhbHVlT3BwcyIsICJmaWxlIjogImZvcmNlLWFwcC9tYWluL2RlZmF1bHQvY2xhc3Nlcy9TbWFsbEFudGlQYXR0ZXJucy5jbHMifX1dLCAibWV0YWRhdGEiOiB7Im9yaWdpbmFsX2NvZGUiOiAiU0VMRUNUIElkLCBOYW1lLCBBbW91bnQsIFN0YWdlTmFtZSBGUk9NIE9wcG9ydHVuaXR5IiwgImNsYXNzX25hbWUiOiAiU21hbGxBbnRpUGF0dGVybnMiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIiwgImNhdGVnb3J5IjogInNvcWxfdW51c2VkX2ZpZWxkcyJ9fSwgeyJydWxlIjogIlNPYmplY3RNYXBJbkFGb3JMb29wIiwgIm1lc3NhZ2UiOiAiVG8gY29uc3VtZSBsZXNzIHJlc291cmNlcywgYnVpbGQgdGhlIG1hcCBmcm9tIGEgbGlzdCBvZiBzT2JqZWN0cyB1c2luZyB0aGUgbWFwIGNvbnN0cnVjdG9yLiBEb24ndCBtYW51YWxseSBidWlsZCBhIG1hcCB1c2luZyBhIEZPUiBsb29wIGFuZCBwdXQoKS4iLCAibG9jYXRpb25zIjogW3sic3RhcnRMaW5lIjogODEsICJjb21tZW50IjogIlNtYWxsQW50aVBhdHRlcm5zLmFjY291bnRzQnlJZCIsICJmaWxlIjogImZvcmNlLWFwcC9tYWluL2RlZmF1bHQvY2xhc3Nlcy9TbWFsbEFudGlQYXR0ZXJucy5jbHMifV0sICJwcmltYXJ5TG9jYXRpb25JbmRleCI6IDAsICJyZXNvdXJjZXMiOiBbImh0dHBzOi8vaGVscC5zYWxlc2ZvcmNlLmNvbS9zL2FydGljbGVWaWV3P2lkPXhjbG91ZC5hcGV4Z3VydV9hbnRpcGF0dGVybl9zb2JqZWN0X21hcF9pbl9mb3JfbG9vcC5odG0mdHlwZT01Il0sICJzZXZlcml0eSI6IDQsICJzdWdnZXN0aW9ucyI6IFt7Im1lc3NhZ2UiOiAiTWFwPElkLEFjY291bnQ+IGFjY01hcCA9IG5ldyBNYXA8SWQsQWNjb3VudD4oW1NFTEVDVCBJZCwgTmFtZSBGUk9NIEFjY291bnRdKTtcblxuLy8gSWYgdGhlIG51bWJlciBvZiB0aGUgcmVjb3JkcyBmcm9tIHRoZSBxdWVyeSBpcyB0b28gbGFyZ2UsIHlvdSBjYW4gYXBwbHkgdGhlIFwicHV0QWxsXCIgbWV0aG9kOlxuXG5NYXA8SWQsQWNjb3VudD4gYWNjTWFwID0gbmV3IE1hcDxJZCxBY2NvdW50PigpO1xuZm9yIChMaXN0PEFjY291bnQ+IHJlY29yZHM6IFtTRUxFQ1QgSWQsIE5hbWUgRlJPTSBBY2NvdW50XSkge1xuICAgIGFjY01hcC5wdXRBbGwocmVjb3Jkcyk7XG59IiwgImxvY2F0aW9uIjogeyJzdGFydExpbmUiOiA4MSwgImNvbW1lbnQiOiAiU21hbGxBbnRpUGF0dGVybnMuYWNjb3VudHNCeUlkIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyJ9fV0sICJtZXRhZGF0YSI6IHsib3JpZ2luYWxfY29kZSI6ICJMaW5lIDgwOiAgICAgICAgTWFwPElkLCBBY2NvdW50PiBhY2NNYXAgPSBuZXcgTWFwPElkLCBBY2NvdW50PigpO1xuTGluZSA4MTogICAgICAgIGZvciAoQWNjb3VudCBhY2MgOiBbU0VMRUNUIElkLCBOYW1lIEZST00gQWNjb3VudF0pIHtcbkxpbmUgODI6ICAgICAgICAgICAgYWNjTWFwLnB1dChhY2MuSWQsIGFjYyk7XG5MaW5lIDgzOiAgICAgICAgfVxuIiwgImNsYXNzX25hbWUiOiAiU21hbGxBbnRpUGF0dGVybnMiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn19LCB7InJ1bGUiOiAiQ29weWluZ0xpc3RPclNldEVsZW1lbnRzVXNpbmdBRm9yTG9vcCIsICJtZXNzYWdlIjogIllvdSdyZSB1c2luZyBhIGxvb3AgdG8gaW5kaXZpZHVhbGx5IGNvcHkgZWxlbWVudHMgZnJvbSBhIGxpc3Qgb3Igc2V0LiBUaGlzIHdhc3RlcyBDUFUgdGltZSBhbmQgY2FuIGV4Y2VlZCBnb3Zlcm5vciBsaW1pdHMuIEFzc2lnbiBmdW5jdGlvbiBvciBxdWVyeSBvdXRwdXRzIGRpcmVjdGx5LCBvciB1c2UgdGhlIGFkZEFsbCgpIG1ldGhvZCB0byBjb3B5IGxpc3Qgb3Igc2V0IGVsZW1lbnRzLiIsICJsb2NhdGlvbnMiOiBbeyJzdGFydExpbmUiOiA4OSwgImNvbW1lbnQiOiAiU21hbGxBbnRpUGF0dGVybnMuY29weUFjY291bnROYW1lcyIsICJmaWxlIjogImZvcmNlLWFwcC9tYWluL2RlZmF1bHQvY2xhc3Nlcy9TbWFsbEFudGlQYXR0ZXJucy5jbHMifV0sICJwcmltYXJ5TG9jYXRpb25JbmRleCI6IDAsICJyZXNvdXJjZXMiOiBbImh0dHBzOi8vaGVscC5zYWxlc2ZvcmNlLmNvbS9zL2FydGljbGVWaWV3P2lkPXhjbG91ZC5hcGV4Z3VydV9hbnRpcGF0dGVybl9jb3B5aW5nX2VsZW1lbnRzX3dpdGhfZm9yX2xvb3AuaHRtJnR5cGU9NSJdLCAic2V2ZXJpdHkiOiA0LCAic3VnZ2VzdGlvbnMiOiBbeyJtZXNzYWdlIjogImNvcHkuYWRkQWxsKG5hbWVzKTtcbi8vICAgICAgICAgZm9yIChTdHJpbmcgbmFtZSA6IG5hbWVzKSB7XG4vLyAgICAgICAgICAgICBjb3B5LmFkZChuYW1lKTtcbi8vICAgICAgICAgfSIsICJsb2NhdGlvbiI6IHsic3RhcnRMaW5lIjogODksICJjb21tZW50IjogIlNtYWxsQW50aVBhdHRlcm5zLmNvcHlBY2NvdW50TmFtZXMiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn19XSwgIm1ldGFkYXRhIjogeyJvcmlnaW5hbF9jb2RlIjogIkxpbmUgODk6ICAgICAgICBmb3IgKFN0cmluZyBuYW1lIDogbmFtZXMpIHtcbkxpbmUgOTA6ICAgICAgICAgICAgY29weS5hZGQobmFtZSk7XG5MaW5lIDkxOiAgICAgICAgfVxuIiwgImNsYXNzX25hbWUiOiAiU21hbGxBbnRpUGF0dGVybnMiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn19LCB7InJ1bGUiOiAiQnVzeUxvb3BEZWxheSIsICJtZXNzYWdlIjogIllvdSdyZSB1c2luZyBhbiBlbXB0eSBsb29wIHRvIGRlbGF5IHByb2dyYW0gZXhlY3V0aW9uLiBUaGlzIHdhc3RlcyBDUFUgdGltZSBhbmQgdXNlcyB0aGUgQXBleCBDUFUgZ292ZXJub3IgbGltaXQuIElmIHRoZSBkZWxheSB3YXMgYWRkZWQgYmVjYXVzZSBvZiBhbiBhc3luYyBqb2IsIHVzZSBTeXN0ZW0uZW5xdWV1ZUpvYiB3aXRoIGEgZGVsYXkgcGFyYW1ldGVyLiIsICJsb2NhdGlvbnMiOiBbeyJzdGFydExpbmUiOiAxMDYsICJjb21tZW50IjogIlNtYWxsQW50aVBhdHRlcm5zLmJ1c3lXYWl0IiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyJ9XSwgInByaW1hcnlMb2NhdGlvbkluZGV4IjogMCwgInJlc291cmNlcyI6IFsiaHR0cHM6Ly9oZWxwLnNhbGVzZm9yY2UuY29tL3MvYXJ0aWNsZVZpZXc/aWQ9eGNsb3VkLmFwZXhndXJ1X2FudGlwYXR0ZXJuX2J1c3lfbG9vcF9kZWxheS5odG0mdHlwZT01Il0sICJzZXZlcml0eSI6IDQsICJtZXRhZGF0YSI6IHsib3JpZ2luYWxfY29kZSI6ICJMaW5lIDEwNTogICAgICAgIExvbmcgZW5kVGltZSA9IHN0YXJ0VGltZSArIDUwMDA7XG5MaW5lIDEwNjogICAgICAgIHdoaWxlIChEYXRlVGltZS5ub3coKS5nZXRUaW1lKCkgPCBlbmRUaW1lKSB7XG5MaW5lIDEwNzogICAgICAgICAgICAvLyBzcGlucyBkb2luZyBub3RoaW5nIHVudGlsIHRoZSBkZWxheSBlbGFwc2VzXG5MaW5lIDEwODogICAgICAgIH1cbkxpbmUgMTA5OiAgICAgICAgU3lzdGVtLmRlYnVnKCdCdXN5IHdhaXQgZmluaXNoZWQuJyk7XG4iLCAiY2xhc3NfbmFtZSI6ICJTbWFsbEFudGlQYXR0ZXJucyIsICJmaWxlIjogImZvcmNlLWFwcC9tYWluL2RlZmF1bHQvY2xhc3Nlcy9TbWFsbEFudGlQYXR0ZXJucy5jbHMifX0sIHsicnVsZSI6ICJVc2luZ1RoZVRlc3RNZXRob2RLZXl3b3JkIiwgIm1lc3NhZ2UiOiAiVGhlIHRlc3RNZXRob2Qga2V5d29yZCBpcyBkZXByZWNhdGVkLiBUbyBzdGF5IHdpdGhpbiBvcmcgbGltaXRzLCBtb3ZlIHRlc3QgbWV0aG9kcyB0byBhIHNlcGFyYXRlIEBpc1Rlc3QgY2xhc3MuIiwgImxvY2F0aW9ucyI6IFt7InN0YXJ0TGluZSI6IDEzNiwgImNvbW1lbnQiOiAiU21hbGxBbnRpUGF0dGVybnMubGVnYWN5VGVzdE1ldGhvZCIsICJmaWxlIjogImZvcmNlLWFwcC9tYWluL2RlZmF1bHQvY2xhc3Nlcy9TbWFsbEFudGlQYXR0ZXJucy5jbHMifV0sICJwcmltYXJ5TG9jYXRpb25JbmRleCI6IDAsICJyZXNvdXJjZXMiOiBbImh0dHBzOi8vaGVscC5zYWxlc2ZvcmNlLmNvbS9zL2FydGljbGVWaWV3P2lkPXhjbG91ZC5hcGV4Z3VydV90ZXN0X2Nhc2VfYW50aXBhdHRlcm5fdXNpbmdfdGVzdG1ldGhvZC5odG0mdHlwZT01Il0sICJzZXZlcml0eSI6IDMsICJtZXRhZGF0YSI6IHsib3JpZ2luYWxfY29kZSI6ICIgICAgcHVibGljIHN0YXRpYyB0ZXN0TWV0aG9kIHZvaWQgbGVnYWN5VGVzdE1ldGhvZCgpIHtcbiIsICJjbGFzc19uYW1lIjogIlNtYWxsQW50aVBhdHRlcm5zIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyJ9fSwgeyJydWxlIjogIlJlZHVuZGFudCBTb3FsIiwgIm1lc3NhZ2UiOiAiQ29uc2lkZXIgbWVyZ2luZyBtdWx0aXBsZSBTT1FMIHF1ZXJpZXMgb24gdGhlIHNhbWUgc09iamVjdCBpbnRvIG9uZSBxdWVyeSB0byByZWR1Y2UgZGF0YWJhc2Ugcm91bmQgdHJpcHMgYW5kIGltcHJvdmUgcGVyZm9ybWFuY2UuIiwgImxvY2F0aW9ucyI6IFt7InN0YXJ0TGluZSI6IDM2LCAiY29tbWVudCI6ICJTbWFsbEFudGlQYXR0ZXJucy50b3RhbE9wZW5BbW91bnQiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn0sIHsic3RhcnRMaW5lIjogMzksICJjb21tZW50IjogIlJlZHVuZGFudCBTT1FMIiwgImZpbGUiOiAiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1NtYWxsQW50aVBhdHRlcm5zLmNscyJ9XSwgInByaW1hcnlMb2NhdGlvbkluZGV4IjogMCwgInJlc291cmNlcyI6IFsiaHR0cHM6Ly9oZWxwLnNhbGVzZm9yY2UuY29tL3MvYXJ0aWNsZVZpZXc/aWQ9eGNsb3VkLmFwZXhndXJ1X2FudGlwYXR0ZXJuX3JlZHVuZGFudF9zb3FsLmh0bSZ0eXBlPTUiXSwgInNldmVyaXR5IjogNCwgInN1Z2dlc3Rpb25zIjogW3sibWVzc2FnZSI6ICJMaXN0PE9wcG9ydHVuaXR5PiBvcGVuT3BwcyA9IFtTRUxFQ1QgQW1vdW50IEZST00gT3Bwb3J0dW5pdHkgV0hFUkUgQWNjb3VudElkID0gOmFjY291bnRJZCBBTkQgSXNDbG9zZWQgPSBmYWxzZV07XG5EZWNpbWFsIHRvdGFsID0gMDtcbmZvciAoT3Bwb3J0dW5pdHkgbyA6IG9wZW5PcHBzKSB7XG4gICAgdG90YWwgKz0gby5BbW91bnQ7XG59XG5TeXN0ZW0uZGVidWcoJ09wZW4gb3BwIGNvdW50OiAnICsgb3Blbk9wcHMuc2l6ZSgpKTsiLCAibG9jYXRpb24iOiB7InN0YXJ0TGluZSI6IDM2LCAiY29tbWVudCI6ICJTbWFsbEFudGlQYXR0ZXJucy50b3RhbE9wZW5BbW91bnQiLCAiZmlsZSI6ICJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvU21hbGxBbnRpUGF0dGVybnMuY2xzIn19XSwgIm1ldGFkYXRhIjogeyJvcmlnaW5hbF9jb2RlIjogIkxpbmUgMzY6ICAgICAgICBMaXN0PE9wcG9ydHVuaXR5PiBmb3JUb3RhbCA9IFtcbkxpbmUgMzc6ICAgICAgICAgICAgU0VMRUNUIEFtb3VudCBGUk9NIE9wcG9ydHVuaXR5IFdIRVJFIEFjY291bnRJZCA9IDphY2NvdW50SWQgQU5EIElzQ2xvc2VkID0gZmFsc2VcbkxpbmUgMzg6ICAgICAgICBdO1xuTGluZSAzOTogICAgICAgIExpc3Q8T3Bwb3J0dW5pdHk+IGZvckNvdW50ID0gW1xuTGluZSA0MDogICAgICAgICAgICBTRUxFQ1QgQW1vdW50IEZST00gT3Bwb3J0dW5pdHkgV0hFUkUgQWNjb3VudElkID0gOmFjY291bnRJZCBBTkQgSXNDbG9zZWQgPSBmYWxzZVxuTGluZSA0MTogICAgICAgIF07XG4iLCAiY2xhc3NfbmFtZSI6ICJTbWFsbEFudGlQYXR0ZXJucyIsICJmaWxlIjogImZvcmNlLWFwcC9tYWluL2RlZmF1bHQvY2xhc3Nlcy9TbWFsbEFudGlQYXR0ZXJucy5jbHMiLCAiY2F0ZWdvcnkiOiAicmVkdW5kYW50X3NvcWxfcXVlcnkifX1d",
6
+ "message": null,
7
+ "violationCount": 20,
8
+ "filesScanned": 1,
9
+ "violationBreakdown": {
10
+ "SOQL_IN_LOOP": 1,
11
+ "SOQL_UNUSED_FIELDS": 3,
12
+ "GGD": 1,
13
+ "SOQL_NEGATIVE_EXPR": 1,
14
+ "SOQL_AGGREGATION": 2,
15
+ "REDUNDANT_SOQL": 1,
16
+ "SOQL_NO_WHERE_LIMIT": 3,
17
+ "SOQL_SORT_IN_APEX": 1,
18
+ "SOQL_FILTER_IN_APEX": 1,
19
+ "BUSY_DELAY_LOOP": 1,
20
+ "COPY_LIST_ELEMENTS_LOOP": 1,
21
+ "DML_IN_LOOP": 1,
22
+ "DEPRECATED_TEST_METHOD_KEYWORD": 1,
23
+ "SOQL_IN_LOOP_1HOP": 1,
24
+ "CREATE_MAP_WITH_LOOP": 1
25
+ }
26
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "scanId": "scan-7f3a91",
3
+ "status": "SUCCEEDED",
4
+ "analysisMode": "static",
5
+ "violationCount": 4,
6
+ "filesScanned": 3,
7
+ "violationBreakdown": {
8
+ "SOQL_IN_LOOP": 1,
9
+ "DML_IN_LOOP": 1,
10
+ "SOQL_NO_WHERE_OR_LIMIT": 1,
11
+ "GGD": 1
12
+ },
13
+ "report": "W3sicnVsZSI6IlNPUUxfSU5fTE9PUCIsIm1lc3NhZ2UiOiJTT1FMIHF1ZXJ5IGV4ZWN1dGVkIGluc2lkZSBhIGZvci1sb29wIG92ZXIgQWNjb3VudHMiLCJzZXZlcml0eSI6MiwibG9jYXRpb24iOnsiZmlsZSI6ImZvcmNlLWFwcC9tYWluL2RlZmF1bHQvY2xhc3Nlcy9BY2NvdW50U2VydmljZS5jbHMiLCJsaW5lIjo0Mn0sImZpeGVzIjpbIk1vdmUgdGhlIHF1ZXJ5IG91dHNpZGUgdGhlIGxvb3A7IGJ1aWxkIGEgTWFwPElkLENvbnRhY3Q+IGZvciBpbi1sb29wIGxvb2t1cHMiXSwicmVzb3VyY2VzIjpbImh0dHBzOi8vZGV2ZWxvcGVyLnNhbGVzZm9yY2UuY29tL2RvY3MvYXBleGd1cnUvc29xbC1pbi1sb29wIl19LHsicnVsZSI6IkRNTF9JTl9MT09QIiwibWVzc2FnZSI6InVwZGF0ZSBzdGF0ZW1lbnQgaW5zaWRlIGEgbG9vcCIsInNldmVyaXR5IjoxLCJsb2NhdGlvbiI6eyJmaWxlIjoiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL0FjY291bnRTZXJ2aWNlLmNscyIsImxpbmUiOjYwfSwiZml4ZXMiOlsiQ29sbGVjdCByZWNvcmRzIGludG8gYSBMaXN0IGFuZCB1cGRhdGUgb25jZSBhZnRlciB0aGUgbG9vcCJdLCJyZXNvdXJjZXMiOltdfSx7InJ1bGUiOiJTT1FMX05PX1dIRVJFX09SX0xJTUlUIiwibWVzc2FnZSI6IlNFTEVDVCB3aXRoIG5laXRoZXIgV0hFUkUgbm9yIExJTUlUIG9uIE9wcG9ydHVuaXR5Iiwic2V2ZXJpdHkiOjIsImxvY2F0aW9uIjp7ImZpbGUiOiJmb3JjZS1hcHAvbWFpbi9kZWZhdWx0L2NsYXNzZXMvUmVwb3J0QnVpbGRlci5jbHMiLCJsaW5lIjoxNX0sImZpeGVzIjpbIkFkZCBhIHNlbGVjdGl2ZSBXSEVSRSBvbiBhbiBpbmRleGVkIGZpZWxkIGFuZCBhIExJTUlUIl0sInJlc291cmNlcyI6W119LHsicnVsZSI6IkdHRCIsIm1lc3NhZ2UiOiJTY2hlbWEuZ2V0R2xvYmFsRGVzY3JpYmUoKSBjYWxsZWQgb24gZXZlcnkgcmVxdWVzdCIsInNldmVyaXR5IjozLCJsb2NhdGlvbiI6eyJmaWxlIjoiZm9yY2UtYXBwL21haW4vZGVmYXVsdC9jbGFzc2VzL1V0aWxzLmNscyIsImxpbmUiOjEyfSwiZml4ZXMiOlsiVXNlIFNPYmplY3RUeXBlLmdldERlc2NyaWJlKCkgZm9yIHRoZSBzcGVjaWZpYyBvYmplY3QiXSwicmVzb3VyY2VzIjpbXX1d",
14
+ "message": null
15
+ }
@@ -0,0 +1,81 @@
1
+ # ApexGuru SFAP Scan API Reference
2
+
3
+ **Base URL (production):** `https://api.salesforce.com/platform/scale/v1-beta.1/apex-guru`
4
+
5
+ The host is chosen from the token's environment (prod/stage/dev); `stage.` and
6
+ `dev.api.salesforce.com` are internal-only. Customers on a prod org always hit
7
+ production. See `authentication.md` for the routing table.
8
+
9
+ **Auth:** `Authorization: Bearer <sfap_api JWT>`. Org comes from the token's
10
+ `tnk` claim (`core/<instance>/<orgId>`) — no org id in the request.
11
+
12
+ ## Call 1 — Submit a scan
13
+
14
+ ```http
15
+ POST /scan
16
+ -H "Authorization: Bearer $JWT"
17
+ -F "file=@project.zip;type=application/zip"
18
+ [ -F "fastMode=true" ] # optional: skip LLM-heavy fix generation → faster/cheaper
19
+ ```
20
+
21
+ - Zip may use **any** layout — the API walks the whole archive and extracts
22
+ every Apex file it finds. No `force-app/` tree at the root is required
23
+ (`build-zip.sh` collects every `.cls`/`.trigger` under the project root,
24
+ preserving relative paths).
25
+ - Limits: **200MB compressed**, **1GB decompressed**.
26
+ - Success → `202`:
27
+
28
+ ```json
29
+ { "scanId": "…", "status": "QUEUED" }
30
+ ```
31
+
32
+ ## Call 2 — Poll for result
33
+
34
+ ```http
35
+ GET /scan/{scanId}
36
+ -H "Authorization: Bearer $JWT"
37
+ ```
38
+
39
+ - Status progression: `QUEUED → RUNNING → SUCCEEDED` (or `FAILED`).
40
+ - Poll ~every **15s**.
41
+ - On `SUCCEEDED`:
42
+
43
+ ```json
44
+ {
45
+ "scanId": "…",
46
+ "status": "SUCCEEDED",
47
+ "analysisMode": "static", // "static" = source-only | "full" = org onboarded, runtime metrics
48
+ "violationCount": 39,
49
+ "filesScanned": 16,
50
+ "violationBreakdown": { "SOQL_IN_LOOP": 15, "DML_IN_LOOP": 8, "GGD": 2 },
51
+ "report": "<base64-encoded JSON array of violations>",
52
+ "message": null
53
+ }
54
+ ```
55
+
56
+ ## The `report` field
57
+
58
+ Base64 → decode → **JSON array of violations**. Each violation carries:
59
+
60
+ - `rule` — the antipattern id (e.g. `SOQL_IN_LOOP`).
61
+ - `message` — human-readable description.
62
+ - `severity` — 1 (Critical) … 5 (Info).
63
+ - source location — `file` + `line`.
64
+ - suggested fix(es).
65
+ - help-doc `resources`.
66
+
67
+ `decode-report.js` tolerates field-name drift (`location`/`locations[0]`,
68
+ `fixes`/`suggestedFixes`, `severity`/`sev`) so minor API-shape changes don't break parsing.
69
+
70
+ ## Status codes
71
+
72
+ | Code | Meaning |
73
+ |------|---------|
74
+ | 202 | Scan accepted (submit) |
75
+ | 200 | Poll OK |
76
+ | 400 | Malformed zip, no Apex inside, or over size limit |
77
+ | 401 | Bad / expired / wrong-env token |
78
+ | 403 | Scan owned by a different org (token `tnk` mismatch) |
79
+ | 404 | Unknown scanId, or archived (~30-day GC) |
80
+
81
+ See `error-handling.md` for resolutions.
@@ -0,0 +1,134 @@
1
+ # Authentication — SFAP Access Token
2
+
3
+ The ApexGuru SFAP Scan API authenticates with an **SFAP access token (JWT)
4
+ carrying the `sfap_api` scope**. There is **no org id parameter** — the target
5
+ org, and the environment (prod/stage/dev) the request is routed to, are both
6
+ derived from the token's `tnk` claim, formatted `core/<instance>/<orgId>`.
7
+ Customers authenticate a production org (`tnk core/prod/<orgId>`), so their
8
+ requests always go to production.
9
+
10
+ ## Where the JWT comes from (Tharun's interim guide)
11
+
12
+ The token is derived from an **authenticated `sf` CLI org**. `resolve-token.sh`
13
+ obtains the org's live session id and exchanges it for the SFAP JWT by calling
14
+ `<instanceUrl>/ide/auth`, which returns `{ "jwt": "...", "message": "..." }`.
15
+
16
+ This is Tharun's **interim** approach — the Code Analyzer team may provide a cleaner
17
+ path later. `resolve-token.sh` is the **single place** that changes when it does;
18
+ everything downstream consumes the token opaquely.
19
+
20
+ ### How the session id is obtained (important)
21
+
22
+ `sf org display --json` **redacts** `accessToken` on recent CLI versions
23
+ (≈2.14x+) — it returns a `[REDACTED]…` placeholder, not a usable token. Sending
24
+ that to `/ide/auth` yields a bare `401 "No session ID sent"`. So the resolver does
25
+ **not** use `sf org display`'s access token. Instead it:
26
+
27
+ 1. reads the (non-redacted) `instanceUrl` from `sf org display --json`,
28
+ 2. gets a frontdoor URL from `sf org open --url-only --json`,
29
+ 3. follows that URL with `curl` to mint the real `sid` session cookie, and
30
+ 4. sends the `sid` as `Authorization: Bearer` to `<instanceUrl>/ide/auth`.
31
+
32
+ The `sid` is a secret: it lives only in a `0600` temp cookie jar that the script
33
+ deletes on exit, and is never echoed.
34
+
35
+ ## How `resolve-token.sh` resolves the token
36
+
37
+ In priority order (first hit wins):
38
+
39
+ 1. **`APEXGURU_SFAP_TOKEN`** environment variable — the raw JWT. Most portable;
40
+ works headless and in CI. Use this in environments where `sf org open` can't
41
+ run (no browser session), supplying a production `sfap_api` JWT directly.
42
+ 2. **`APEXGURU_SFAP_TOKEN_FILE`** environment variable — a path to a file containing
43
+ the JWT (whitespace trimmed). Keeps the token out of shell history.
44
+ 3. **`sf` CLI → frontdoor `sid` → `<instanceUrl>/ide/auth`** — derives the JWT from
45
+ an authenticated **production** org. Requires `sf`, `jq`, and `curl`. Org
46
+ selection: `--org <alias>` flag, else the `APEXGURU_SF_ORG` env var, else the
47
+ CLI's default/target org. The user just needs to be logged in
48
+ (`sf org login web`).
49
+
50
+ If none succeed, the script returns:
51
+
52
+ ```json
53
+ {"error":"no SFAP token found","hint":"Sign in to an authorized Salesforce org to run an ApexGuru scan and compare your code against production performance data."}
54
+ ```
55
+
56
+ ### Setting up the `sf` CLI path
57
+
58
+ ```bash
59
+ # Log in once to a PRODUCTION org (My Domain or internal login host):
60
+ sf org login web --instance-url "https://<your-prod-host>" --alias <your-alias>
61
+
62
+ # Then the skill derives the JWT automatically. To target a specific org:
63
+ bash run-scan.sh <zip> <raw-out.json> --org <your-alias>
64
+ ```
65
+
66
+ The `/ide/auth` response also carries a `message` field; only `jwt` is consumed.
67
+ Treat the derived JWT as a secret — the scripts never echo it (see the mandatory
68
+ script rules in SKILL.md). `resolve-token.sh` never prints the token to stdout:
69
+ it writes the JWT to a `0600` temp file and returns only the path in a
70
+ `tokenFile` field; `run-scan.sh` reads that file into memory and deletes it
71
+ immediately.
72
+
73
+ > **Note:** some orgs gate `/ide/auth` behind MFA enrollment — the exchange then
74
+ > returns an HTML redirect to a two-factor setup page instead of a JWT. If that
75
+ > happens, either complete MFA enrollment for that org or supply a production
76
+ > `sfap_api` JWT directly via `APEXGURU_SFAP_TOKEN`.
77
+
78
+ ## Local pre-flight token check (no network)
79
+
80
+ Once a token is found, `resolve-token.sh` pipes it to `validate-token.js`, which
81
+ decodes the JWT's freely-readable header/body claims (it does **not** verify the
82
+ signature — only the server can) to catch the two things behind almost every
83
+ `401` **before** we zip and upload, and to detect the token's environment:
84
+
85
+ 1. **Missing scope** — the `scp`/`scope` claim doesn't include `sfap_api`.
86
+ 2. **Expired** — `exp` is in the past.
87
+
88
+ It also reads the environment from the `tnk` instance segment (and `iss` host) —
89
+ `core/prod/...` → prod, `core/stagecomstg2/...` → stage, `core/falcondeva/...` →
90
+ dev — and reports it as `detectedEnv` so `resolve-token.sh` routes to the
91
+ matching host. This is **not** a block: a stage/dev token routes to the stage/dev
92
+ endpoint instead of being rejected.
93
+
94
+ Only **provable** failures block (exit 1 with a clear `error`/`hint`). Anything the
95
+ script can't read — an opaque non-JWT token, or a missing claim — is a non-fatal
96
+ warning, so this never blocks a valid token it simply can't introspect. The token
97
+ is passed on **stdin**, never as a command-line argument, so it stays out of the
98
+ process list.
99
+
100
+ Example fail-fast message (instead of a bare HTTP 401 deep in the poll loop):
101
+
102
+ ```json
103
+ {"ok":false,"error":"token scope does not include sfap_api","hint":"Re-mint the token with the sfap_api scope. See references/authentication.md."}
104
+ ```
105
+
106
+ ## Setup for the user
107
+
108
+ ```bash
109
+ # Normal path: just log in to a production org with the sf CLI
110
+ # (the JWT is derived automatically).
111
+ sf org login web --instance-url "https://<your-prod-host>" --alias <your-alias>
112
+
113
+ # Override A: env var for the session (CI/headless, or to bypass sf CLI)
114
+ export APEXGURU_SFAP_TOKEN="eyJ...<production sfap_api JWT>..."
115
+
116
+ # Override B: token file (not echoed into history)
117
+ export APEXGURU_SFAP_TOKEN_FILE="$HOME/.apexguru/sfap-token"
118
+ ```
119
+
120
+ ## Endpoint routing
121
+
122
+ The base URL is chosen from the token's detected environment, so the request
123
+ always lands where the token was issued:
124
+
125
+ | Env | Host | Base URL |
126
+ |-------|-----------------------------|-----------------------------------------------------------------|
127
+ | prod | `api.salesforce.com` | `https://api.salesforce.com/platform/scale/v1-beta.1/apex-guru` |
128
+ | stage | `stage.api.salesforce.com` | `https://stage.api.salesforce.com/platform/scale/v1-beta.1/apex-guru` |
129
+ | dev | `dev.api.salesforce.com` | `https://dev.api.salesforce.com/platform/scale/v1-beta.1/apex-guru` |
130
+
131
+ There is no `--env` flag: routing is automatic from the `tnk` claim, and an
132
+ undetectable environment defaults to prod. Customers authenticate a production
133
+ org, so they always hit `api.salesforce.com`; the stage/dev hosts exist for
134
+ internal testing against non-prod orgs.
@@ -0,0 +1,56 @@
1
+ # Error Handling Guide
2
+
3
+ `run-scan.sh` emits `{error, httpStatus, status, hint}` on failure and maps each HTTP
4
+ status to an actionable hint. Relay the hint to the user.
5
+
6
+ ## HTTP status codes
7
+
8
+ | Code | Likely cause | Resolution |
9
+ |------|--------------|------------|
10
+ | **400** | Malformed zip, no Apex inside, or over size limit | Re-package with `build-zip.sh` (collects every `.cls`/`.trigger` and checks the 200MB compressed limit). If genuinely large, scope to a subset of the project. Decompressed limit is 1GB. |
11
+ | **401** | Token bad or expired | Re-authenticate the Salesforce org (or supply a fresh `sfap_api` JWT via `APEXGURU_SFAP_TOKEN`). The endpoint is routed to the token's environment automatically. See `authentication.md`. |
12
+ | **403** | Scan owned by a different org | The token's `tnk`-claim org must match the scan owner. Use the token for the org that submitted the scan. |
13
+ | **404** | Unknown `scanId`, or scan archived | Scans are GC'd after ~30 days. Re-submit to get a fresh `scanId`. |
14
+
15
+ ## Scan `status: FAILED`
16
+
17
+ The poll returns `FAILED` with a `message`. Surface the message verbatim, address the
18
+ stated cause, and re-submit. This is distinct from an HTTP error — the request
19
+ succeeded but the scan itself failed server-side.
20
+
21
+ ## Timeout (scan didn't finish)
22
+
23
+ `run-scan.sh` polls up to `--max-polls` × `--interval` seconds (default 40 × 15s =
24
+ 10 min). If it times out:
25
+
26
+ - Large projects legitimately take longer → re-run with `--max-polls 80`.
27
+ - Or add `--fast` to skip LLM-heavy fix generation.
28
+
29
+ ## `analysisMode` and the three ApexGuru states
30
+
31
+ **Not an error.** The API's `analysisMode` plus the presence of runtime metrics
32
+ (`cpu_time_percentage` on any violation) distinguish three states. `decode-report.js`
33
+ handles all three automatically — this is background for interpreting the output:
34
+
35
+ | State | `analysisMode` | Runtime metrics | Header | What it means |
36
+ |-------|----------------|-----------------|--------|---------------|
37
+ | Not onboarded | `static` | none | **Static only** | The org is **not onboarded** to ApexGuru — only source-only analysis ran. |
38
+ | Onboarded, no runtime data yet | `full` | none | **Static only** | The org **is onboarded**, but there's no runtime data for this code yet. Result is static-equivalent. |
39
+ | Onboarded, enriched | `full` | present | **Production insights** | Onboarded **and** runtime metrics were applied (CPU hotspots, severity adjusted from production performance). |
40
+
41
+ Runtime data is populated by ApexGuru's weekend runs, or on demand from Scale
42
+ Center. So `full` + no runtime data is expected for a freshly-onboarded org or
43
+ newly-added code — it is **not** an error, and re-scanning won't change it until
44
+ runtime data exists. `decode-report.js --present` prints the correct guidance line
45
+ for each state ("generate a runtime report in Scale Center"); print it verbatim.
46
+
47
+ ## Missing local prerequisites
48
+
49
+ | Symptom | Fix |
50
+ |---------|-----|
51
+ | `no SFAP token found` | No authenticated org and no token env var. Print the script's `hint` verbatim as the entire message — do not add framing or alternative instructions: "Sign in to an authorized Salesforce org to run an ApexGuru scan and compare your code against production performance data." |
52
+ | `token scope does not include sfap_api` | Re-mint the token with the `sfap_api` scope. Pre-empts a 401. |
53
+ | `token expired Ns ago` | Re-mint a fresh SFAP token and retry. Pre-empts a 401. |
54
+ | `no Apex (.cls/.trigger) files found` | Point `build-zip.sh` at a folder that contains Apex classes or triggers (any layout — an sfdx project, a `force-app/` subtree, or a loose folder of `.cls` files) |
55
+ | `zip: command not found` / `jq: command not found` | Install the missing tool (`brew install jq`, etc.) |
56
+ | `network error submitting scan` | Check connectivity/VPN to the API host |
@@ -0,0 +1,28 @@
1
+ # ApexGuru Violation Catalog
2
+
3
+ Performance antipatterns ApexGuru detects, with what they mean and the typical fix.
4
+ Use this to explain a violation when the user asks "what does this mean / how do I
5
+ fix it?". The API's `report` carries per-violation `message`, `fixes`, and help-doc
6
+ `resources` — prefer those when present; this catalog is the fallback explanation.
7
+
8
+ | Rule (`rule`) | What it flags | Why it hurts | Typical fix |
9
+ |---------------|---------------|--------------|-------------|
10
+ | `SOQL_IN_LOOP` | A SOQL query inside a `for`/`while` loop | Each iteration issues a query → hits the 100-SOQL governor limit fast; slow | Move the query outside the loop; query once and build a `Map<Id, SObject>` keyed for lookup inside the loop |
11
+ | `DML_IN_LOOP` | `insert`/`update`/`delete`/`upsert` inside a loop | Each iteration issues DML → hits the 150-DML limit; slow | Collect records into a `List` and perform one DML statement after the loop |
12
+ | `GGD` | `Schema.getGlobalDescribe()` usage | Describes **every** object in the org — expensive, grows with org size | Use targeted describes (`SObjectType.getDescribe()`, `Schema.describeSObjects([...])`) for only the objects needed |
13
+ | `SOQL_NO_WHERE_OR_LIMIT` | SOQL with neither `WHERE` nor `LIMIT` | Full-table scan; can return huge result sets and blow the heap / row limits | Add a selective `WHERE` clause and/or a `LIMIT`; ensure filters are on indexed fields |
14
+ | `SOQL_UNUSED_FIELDS` | SELECTed fields never read | Wastes query CPU/heap fetching unused columns | Select only fields the code actually uses |
15
+
16
+ ## Severity mapping
17
+
18
+ ApexGuru severities follow the standard 1–5 scale: **1 = Critical, 2 = High,
19
+ 3 = Moderate, 4 = Low, 5 = Info.** `DML_IN_LOOP` and `SOQL_IN_LOOP` are usually the
20
+ highest-impact (governor-limit) findings.
21
+
22
+ ## Static vs. full attribution
23
+
24
+ - **Static** findings come from source analysis alone — the antipattern exists in the
25
+ code regardless of runtime.
26
+ - **Full** findings are enriched with production metrics — e.g. a `SOQL_IN_LOOP`
27
+ that actually executed against large data volumes in production is prioritized
28
+ higher. Always label which mode produced the results.
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env bash
2
+ # Package a customer's Apex into a .zip for the ApexGuru SFAP Scan API.
3
+ #
4
+ # The API walks the ENTIRE uploaded archive and extracts every Apex file it
5
+ # finds — it does NOT require a force-app/ tree at the root (confirmed against
6
+ # production). So we scan whatever the customer points us at: collect every
7
+ # Apex source file (`.cls` / `.trigger`) under <project-root>, preserving its
8
+ # relative path, and zip that. A plain sfdx project, a loose folder of classes,
9
+ # or a deeply-nested monorepo subtree all work.
10
+ #
11
+ # Usage: bash build-zip.sh <project-root> <output-zip-path>
12
+ #
13
+ # <project-root> is any folder that contains Apex somewhere beneath it (an sfdx
14
+ # project root, a force-app/ subtree, or an ad-hoc folder of .cls files).
15
+ #
16
+ # Output (stdout, single line JSON):
17
+ # {"zip":"<abs path>","bytes":123,"humanSize":"1.2M","apexFileCount":N,"scanRoot":"<path>"}
18
+ # On failure: {"error":"...","hint":"..."} and exit 1.
19
+ #
20
+ # API limits enforced here (fail fast, before upload): 200MB compressed.
21
+ # (1GB decompressed is enforced server-side; we cannot cheaply predict it.)
22
+ set -euo pipefail
23
+
24
+ MAX_COMPRESSED_BYTES=$((200 * 1024 * 1024))
25
+
26
+ PROJECT_ROOT="${1:-}"
27
+ OUT_ZIP="${2:-}"
28
+
29
+ if [ -z "$PROJECT_ROOT" ] || [ -z "$OUT_ZIP" ]; then
30
+ printf '{"error":"missing args","hint":"usage: build-zip.sh <project-root> <output-zip-path>"}\n'
31
+ exit 1
32
+ fi
33
+
34
+ if [ ! -d "$PROJECT_ROOT" ]; then
35
+ printf '{"error":"project root not found: %s","hint":"pass a folder that contains Apex (.cls/.trigger) files"}\n' "$PROJECT_ROOT"
36
+ exit 1
37
+ fi
38
+
39
+ # Resolve absolute paths.
40
+ ROOT_ABS="$(cd "$PROJECT_ROOT" && pwd)"
41
+ case "$OUT_ZIP" in
42
+ /*) OUT_ABS="$OUT_ZIP" ;;
43
+ *) OUT_ABS="$(pwd)/$OUT_ZIP" ;;
44
+ esac
45
+
46
+ rm -f "$OUT_ABS"
47
+
48
+ # The set of Apex source files under the root (relative paths, noise excluded).
49
+ # Defined once as a function so the count pass and the zip pass use the exact
50
+ # same list. `zip -@` reads a newline-delimited list, so we emit newline-
51
+ # terminated relative paths with the leading "./" stripped.
52
+ apex_files() {
53
+ find . -type f \( -name '*.cls' -o -name '*.trigger' \) \
54
+ -not -path '*/node_modules/*' -not -path '*/.git/*' -print \
55
+ | sed 's#^\./##'
56
+ }
57
+
58
+ APEX_COUNT=0
59
+ while IFS= read -r _; do
60
+ APEX_COUNT=$((APEX_COUNT + 1))
61
+ done < <(cd "$ROOT_ABS" && apex_files)
62
+
63
+ if [ "$APEX_COUNT" -eq 0 ]; then
64
+ printf '{"error":"no Apex (.cls/.trigger) files found under %s","hint":"point build-zip.sh at a folder that contains Apex classes or triggers"}\n' "$ROOT_ABS"
65
+ exit 1
66
+ fi
67
+
68
+ # Feed the file list to zip via stdin (-@) so we never hit ARG_MAX on large
69
+ # projects. Paths are relative to ROOT_ABS, so the archive mirrors the project
70
+ # layout (the API re-walks it regardless of structure).
71
+ ( cd "$ROOT_ABS" && apex_files | zip -q -X "$OUT_ABS" -@ >/dev/null )
72
+
73
+ if [ ! -f "$OUT_ABS" ]; then
74
+ printf '{"error":"zip creation failed","hint":"check write permissions for %s"}\n' "$OUT_ABS"
75
+ exit 1
76
+ fi
77
+
78
+ BYTES=$(wc -c < "$OUT_ABS" | tr -d '[:space:]')
79
+ if [ "$BYTES" -gt "$MAX_COMPRESSED_BYTES" ]; then
80
+ printf '{"error":"zip is %s bytes, over the 200MB compressed limit","hint":"scope the scan to a subset of the project or split it"}\n' "$BYTES"
81
+ exit 1
82
+ fi
83
+
84
+ HUMAN=$(echo "$BYTES" | awk '{ split("B K M G", u); s=$1; i=1; while (s>=1024 && i<4){s/=1024; i++} printf (i==1 ? "%d%s" : "%.1f%s"), s, u[i] }')
85
+
86
+ jq -cn --arg zip "$OUT_ABS" --argjson bytes "$BYTES" --arg human "$HUMAN" --argjson count "$APEX_COUNT" --arg root "$ROOT_ABS" \
87
+ '{zip:$zip, bytes:$bytes, humanSize:$human, apexFileCount:$count, scanRoot:$root}'