[
  {
    "path": ".github/FUNDING.yml",
    "content": "github: [reposaur, crqra]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: Bug Report\ndescription: File a bug report\n\ntitle: \"[Bug]: \"\nlabels: [\"bug\", \"triage\"]\n\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to fill out this bug report and improving Reposaur!\n\n  - type: textarea\n    id: description\n    attributes:\n      label: Description\n      description: Describe what happened\n      placeholder: Tell us what you see!\n    validations:\n      required: true\n\n  - type: textarea\n    id: expected\n    attributes:\n      label: Expectation\n      description: Describe what you expected to have happened\n      placeholder: Tell us what you expected to see!\n    validations:\n      required: true\n\n  - type: input\n    id: version\n    attributes:\n      label: Version\n      description: What's the version of Reposaur you're running?\n      placeholder: 0.0.0\n\n  - type: textarea\n    id: logs\n    attributes:\n      label: Relevant log output\n      description: |\n        Please copy and paste any relevant log output.\n        This will be automatically formatted into code, so no need for backticks.\n      render: shell\n\n  - type: checkboxes\n    id: terms\n    attributes:\n      label: Code of Conduct\n      description: |\n        By submitting this issue, you agree to follow our\n        [Code of Conduct](https://github.com/reposaur/reposaur/blob/main/CODE_OF_CONDUCT.md)\n      options:\n        - label: I agree to follow Reposaur's Code of Conduct\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: true\ncontact_links:\n  - name: Ask a question\n    url: https://github.com/orgs/reposaur/discussions\n    about: Community Support Forum\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "content": "name: Feature Request\ndescription: Suggest a new idea or feature to add to Reposaur\n\ntitle: \"[Feature]: \"\nlabels: [\"enhancement\", \"triage\"]\n\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to suggest new ideas and features,\n        improving Reposaur!\n\n  - type: textarea\n    id: description\n    attributes:\n      label: What would you like to see improved?\n      description: |\n        Is there something challenging or frustrating about Reposaur\n        that you're trying to improve? How would this improvement make your\n        experience better?\n    validations:\n      required: true\n\n  - type: textarea\n    id: ideal-solution\n    attributes:\n      label: What would be the ideal solution?\n    validations:\n      required: true\n\n  - type: textarea\n    id: good-solution\n    attributes:\n      label: What would be a \\\"good enough\\\" solution?\n    validations:\n      required: true\n\n  - type: checkboxes\n    id: terms\n    attributes:\n      label: Code of Conduct\n      description: |\n        By submitting this issue, you agree to follow our\n        [Code of Conduct](https://github.com/reposaur/reposaur/blob/main/CODE_OF_CONDUCT.md)\n      options:\n        - label: I agree to follow Reposaur's Code of Conduct\n          required: true\n"
  },
  {
    "path": ".github/codeowners",
    "content": "* @crqra"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"gomod\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Test\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\nenv:\n  GO111MODULE: on\n\njobs:\n  golangci-lint:\n    name: Golang CI Lint\n    runs-on: ubuntu-latest\n    steps:\n      - name: Setup Go\n        uses: actions/setup-go@v2\n        with:\n          go-version: \"1.18\"\n\n      - name: Checkout\n        uses: actions/checkout@v3\n\n      - name: Golang CI Lint\n        uses: golangci/golangci-lint-action@v3.1.0\n        with:\n          version: latest\n          args: --verbose\n\n  test-unix:\n    strategy:\n      fail-fast: false\n      matrix:\n        platform:\n          - ubuntu\n          - macOS\n        go:\n          - 18\n    name: \"${{ matrix.platform }} | 1.${{ matrix.go }}.x\"\n    runs-on: ${{ matrix.platform }}-latest\n    steps:\n      - name: Setup Go\n        uses: actions/setup-go@v2\n        with:\n          go-version: 1.${{ matrix.go }}.x\n\n      - name: Checkout\n        uses: actions/checkout@v3\n\n      - name: Setup Cache\n        uses: actions/cache@v3\n        with:\n          path: ~/go/pkg/mod\n          key: ${{ runner.os }}-1.${{ matrix.go }}.x-${{ hashFiles('**/go.sum') }}\n          restore-keys: ${{ runner.os }}-1.${{ matrix.go }}.x-\n\n      - name: Test\n        run: go test ./...\n\n  test-win:\n    name: MINGW64\n    defaults:\n      run:\n        shell: msys2 {0}\n    runs-on: windows-latest\n    steps:\n      - name: Setup MSYS2\n        uses: msys2/setup-msys2@v2\n        with:\n          msystem: MINGW64\n          update: true\n          install: >\n            git\n            make\n            unzip\n            mingw-w64-x86_64-go\n\n      - name: Checkout\n        uses: actions/checkout@v3\n\n      - name: Setup Cache\n        uses: actions/cache@v3\n        with:\n          path: ~/go/pkg/mod\n          key: ${{ runner.os }}-${{ matrix.go }}-${{ hashFiles('**/go.sum') }}\n          restore-keys: ${{ runner.os }}-${{ matrix.go }}-\n\n      - name: Test\n        run: go test ./...\n"
  },
  {
    "path": ".gitignore",
    "content": "# Used for local tests only\n/config.yaml\n/policy/\n/testdata/events/_*.json\ndist/\nbin/\n\n# Generated\n/completions\n\n# Editors\n/.idea\n/.vscode\n/.fleet"
  },
  {
    "path": ".goreleaser.yml",
    "content": "before:\n  hooks:\n    - go mod tidy\n    - go vet ./...\n    - ./scripts/completions.sh\n\nbuilds:\n  - id: rsr\n    binary: rsr\n    main: ./cmd/rsr/rsr.go\n    ldflags:\n      - -s -w -X github.com/reposaur/reposaur/internal/build.Version={{.Version}}\n    env:\n      - CGO_ENABLED=0\n    goos:\n      - linux\n      - windows\n      - darwin\n  - id: reposaur\n    binary: reposaur\n    main: ./cmd/rsr/rsr.go\n    ldflags:\n      - -s -w -X github.com/reposaur/reposaur/internal/build.Version={{.Version}}\n    env:\n      - CGO_ENABLED=0\n    goos:\n      - linux\n      - windows\n      - darwin\n\narchives:\n  - replacements:\n      darwin: Darwin\n      linux: Linux\n      windows: Windows\n      386: i386\n      amd64: x86_64\n    format_overrides:\n      - goos: windows\n        format: zip\n    files:\n      - README.md\n      - LICENSE\n      - completions/*\n\nchecksum:\n  name_template: \"checksums.txt\"\n\nsnapshot:\n  name_template: \"{{ incpatch .Version }}-next\"\n\nchangelog:\n  use: github\n  sort: asc\n  filters:\n    exclude:\n      - \"^test:\"\n      - \"^chore:\"\n      - \"^build:\"\n  groups:\n    - title: 'New Features and updates'\n      regexp: \"^.*feat[(\\\\w)]*:+.*$\"\n      order: 0\n    - title: 'Bug fixes'\n      regexp: \"^.*fix[(\\\\w)]*:+.*$\"\n      order: 10\n    - title: 'Documentation updates'\n      regexp: \"^.*docs[(\\\\w)]*:+.*$\"\n      order: 20\n    - title: Other work\n      order: 999\n\nrelease:\n  github:\n    owner: reposaur\n    name: reposaur\n  prerelease: auto\n  footer: |\n    **Full Changelog**: https://github.com/reposaur/reposaur/compare/{{ .PreviousTag }}...{{ .Tag }}\n\n    ## What to do next?\n\n    - Read the [documentation](https://docs.reposaur.com)\n    - Join our [Slack](https://slack.reposaur.com)\n    - Follow us on [Twitter](https://twitter.com/reposaurhq)\n\nbrews:\n  - tap:\n      owner: reposaur\n      name: homebrew-tap\n    commit_author:\n      name: goreleaserbot\n      email: goreleaser@carlosbecker.com\n    commit_msg_template: \"chore: brew formula update for {{ .ProjectName }} version {{ .Tag }}\"\n    folder: Formula\n    homepage: \"https://reposaur.com\"\n    description: \"Open source compliance tool for development platforms\"\n    license: \"MIT\"\n    test: |\n      system \"#{bin}/rsr\"\n    install: |-\n      bin.install \"rsr\"\n      bash_completion.install \"completions/rsr.bash\" => \"rsr\"\n      zsh_completion.install \"completions/rsr.zsh\" => \"_rsr\"\n      fish_completion.install \"completions/rsr.fish\"\n\nnfpms:\n  - vendor: Reposaur\n    homepage: https://reposaur.com/\n    maintainer: João Cerqueira <oss@cerqueira.io>\n    description: |-\n      The open source compliance tool for development platforms.\n    license: MIT\n    contents:\n      - src: ./completions/rsr.bash\n        dst: /usr/share/bash-completion/completions/rsr\n        file_info:\n          mode: 0644\n      - src: ./completions/rsr.fish\n        dst: /usr/share/fish/completions/rsr.fish\n        file_info:\n          mode: 0644\n      - src: ./completions/rsr.zsh\n        dst:  /usr/share/zsh/vendor-completions/_rsr\n        file_info:\n          mode: 0644\n      - src: ./LICENSE\n        dst: /usr/share/doc/rsr/copyright\n        file_info:\n          mode: 0644\n    formats:\n      - apk\n      - deb\n      - rpm\n    section: utils\n    priority: extra\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\noss@cerqueira.io.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior,  harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nBeforehand, thank you for considering contributing to Reposaur! We welcome and\nappreciate any help we can get.\n\nContributors are expected to follow our [Code of Conduct](CODE_OF_CONDUCT.md).\n\n## Feedback and Questions\n\nWe appreciate any feedback we can get and are happy to answer any questions you\nmight have!\n\nReach out to us in [Discussions][discussions] or in our [Slack Workspace][slack].\n\n## Bug Reporting and Feature Requests\n\n### Bug Reports\n\nIf you've found an issue in the CLI, SDK or Policy Engine, please\n[open a bug report][bug-report]. We appreciate the feedback and will try to help\nas soon as possible. The form will guide you on how to report the bug.\n\n### Feature Requests\n\nIf you've an exiting idea, new use case or anything else, we'd love to hear it!\nPlease, [open a feature request][feature-request] and share it with the community!\nThe form will guide you on how to request a new feature.\n\n## Development\n\nTo get your development environment ready you'll need to have the following\ninstalled:\n\n- [Go][go] >= 1.18\n- [Task][task] >= 3.0\n\n### Setting up\n\nFork the repository to your account and clone it to your machine. Build for the\nfirst time and make sure everything is working as expected:\n\n```console\n$ task build\n```\n\nIf you don't have Task installed you can issue the following commands:\n\n```console\ngo mod tidy\ngo build -o ./.bin/rsr ./cmd/rsr/rsr.go \\\n    -ldflags \"-s -w -X github.com/reposaur/reposaur/internal/build.Version=devel\"\n```\n\nAfter the command above you should have `rsr` available in `./.bin`:\n\n```console\n$ ./.bin/rsr --version\nrsr version devel\n```\n\nHappy coding!\n\n### Creating a Pull Request\n\nWe don't have any rigid structure for Pull Requests right now, although that's\nexpected to change in the future.\n\nFor now, just explain briefly what your changes address and link any related\nissues or other Pull Requests.\n\nCreating an [issue][issues] prior to the Pull Request is highly recommended to\navoid multiple people working on the same issue, resulting in duplicated effort.\n\nVisit the [Pull Requests][pulls] page.\n\n## Releasing\n\nTo create new releases you'll need to have the following tools installed:\n\n- [GoReleaser][goreleaser] >= 1.9\n- [svu][svu] >= 1.9\n\n[discussions]: https://github.com/orgs/reposaur/discussions\n[issues]: https://github.com/reposaur/reposaur/issues\n[pulls]: https://github.com/reposaur/reposaur/pulls\n[bug-report]: https://github.com/reposaur/reposaur/issues/new?assignees=&labels=bug%2Ctriage&template=bug_report.yml&title=%5BBug%5D%3A+\n[feature-request]: https://github.com/reposaur/reposaur/issues/new?assignees=&labels=enhancement%2Ctriage&template=feature_request.yml&title=%5BFeature%5D%3A+\n[slack]: https://slack.reposaur.com\n[go]: https://go.dev/\n[task]: https://taskfile.dev/\n[goreleaser]: https://goreleaser.com\n[svu]: https://github.com/caarlos0/svu\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2022 João Cerqueira and Reposaur contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\">\n\n[![logo][logo]][website]\n\n# Reposaur\n\n[![go-report][go-report-badge]][go-report]\n[![tests-workflow][tests-workflow-badge]][tests-workflow]\n[![license][license-badge]]()\n[![discussions][discussions-badge]][discussions]\n[![discord][discord-badge]][discord-invite]\n[![twitter][twitter-badge]][twitter]\n\n**Reposaur is the open source compliance tool for development platforms.**\n\nAudit, verify and report on your data and configurations easily with pre-defined and/or custom policies. <br />\nSupports GitHub. GitLab, BitBucket and Gitea support soon.\n⚠️ before 1.0.0 expect some bugs and API changes ⚠️\n[Getting started](#getting-started) •\n[Installation](#installation) •\n[Documentation][docs] •\n[Guides](#guides) •\n[Integrations](#integrations)\n\n</div>\n\n# Getting Started\n\nHave you ever felt like you don't know what's happening in your GitHub/GitLab/BitBucket repositories? Between 100s or 1000s of them it's hard to make sure every single one is compliant to certain security and best practices guidelines.\n\nReposaur is here to fix that, empowering you to focus on your work instead of hunting for issues and misconfigurations.\n\n## Features\n\n- Custom policies using the [Rego][rego] policy language ([learn more][docs-policy])\n- A simple, composable and easy-to-use CLI ([learn more][docs-cli])\n- Extendable using a straightforward SDK (written in Go)\n- Reports follow the standard SARIF format, enabling easy integrations with different systems\n- Policies can be unit tested, guaranteeing they work as expected\n- Integration with the major development platforms (see [Integrations](#integrations))\n- Easily integrate new platforms using the SDK\n\n## Guides\n\n- [Writing your first policy](https://docs.reposaur.com/guides/writing-your-first-policy)\n\n# Installation\n\n#### Homebrew Tap\n\n```shell\n$ brew install reposaur/tap/reposaur\n```\n\n#### DEB, RPM and APK Packages\n\nDownload the `.deb`, `.rpm` or `.apk` packages from the [releases page][releases]\nand install them with the appropriate tools.\n\n#### Go\n\n```shell\n$ go install github.com/reposaur/reposaur/cmd/rsr@latest\n```\n\n#### Script\n\nThe script will download the latest release to a temporary directory and decompress\nit to `$HOME/.reposaur`.\n\n```shell\n$ curl -sfL https://get.reposaur.com | bash\n```\n\n# Integrations\n\n| Platform               | Status      | Details                                                                                   |\n|------------------------|-------------|-------------------------------------------------------------------------------------------|\n| [GitHub][github]       | In progress | [Provider][github-provider] • [GitHub App][github-app] • [GitHub Actions][github-actions] |\n| [GitLab][gitlab]       | Planned     | N/A                                                                                       |\n| [Gitea][gitea]         | Planned     | N/A                                                                                       |\n| [BitBucket][bitbucket] | Not planned | N/A                                                                                       |\n\n# Contributing\n\nWe appreciate every contribution, thanks for considering it!\n\n**TLDR;**\n\n- [Open an issue][issues] if you have a problem or found a bug\n- [Open a Pull Request][pulls] if you have a suggestion, improvement or bug fix\n- [Open a Discussion][discussions] if you have questions or want to discuss ideas\n\nCheck our [Contributing Guide](CONTRIBUTING.md) for more detailed information.\n\n# License\n\nThis project is released under the [MIT License](LICENSE).\n\n[website]: https://reposaur.com\n[docs]: https://docs.reposaur.com\n[docs-policy]: https://docs.reposaur.com/policy\n[docs-cli]: https://docs.reposaur.com/cli/exec\n[issues]: https://github.com/reposaur/reposaur/issues\n[pulls]: https://github.com/reposaur/reposaur/pulls\n[logo]: https://user-images.githubusercontent.com/8532541/169531963-bafd3cbf-dadd-486d-83cc-10a4d39c1dbc.png\n[rego]: https://www.openpolicyagent.org/docs/latest/policy-language/\n[license]: https://github.com/reposaur/reposaur/blob/main/LICENSE\n[license-badge]: https://img.shields.io/github/license/reposaur/reposaur?style=flat-square&color=blueviolet\n[go-report]: https://goreportcard.com/report/github.com/reposaur/reposaur\n[go-report-badge]: https://goreportcard.com/badge/github.com/reposaur/reposaur?style=flat-square&color=blueviolet\n[tests-workflow]: https://github.com/reposaur/reposaur/actions/workflows/test.yml\n[tests-workflow-badge]: https://img.shields.io/github/workflow/status/reposaur/reposaur/Test?label=tests&style=flat-square\n[discussions]: https://github.com/orgs/reposaur/discussions\n[discussions-badge]: https://img.shields.io/github/discussions/reposaur/reposaur?style=flat-square&color=blueviolet\n[discord-invite]: https://discord.gg/jpx4sqkQYY\n[discord-badge]: https://img.shields.io/discord/1021712577132240898?label=discord&style=flat-square&color=blueviolet\n[twitter]: https://twitter.com/reposaurhq\n[twitter-badge]: https://img.shields.io/badge/twitter-%40reposaurhq-blueviolet?style=flat-square\n[github]: https://github.com\n[github-app]: https://docs.reposaur.com/integrations/github-app\n[github-actions]: https://docs.reposaur.com/integrations/github-actions/setup-reposaur\n[github-provider]: https://docs.reposaur.com/\n[gitlab]: https://gitlab.com\n[gitea]: https://gitea.io\n[bitbucket]: https://bitbucket.org\n[releases]: https://github.com/reposaur/reposaur/releases/latest\n"
  },
  {
    "path": "Taskfile.yaml",
    "content": "# https://taskfile.dev\n\nversion: \"3\"\n\ntasks:\n  deps:\n    run: once\n    cmds:\n      - go mod tidy\n    silent: true\n\n  build:\n    deps: [deps]\n    vars:\n      VERSION: devel\n    cmds:\n      - go build -ldflags \"-s -w -X github.com/reposaur/reposaur/internal/build.Version={{.VERSION}}\" -o ./bin/rsr ./cmd/rsr/rsr.go\n    silent: true\n\n  release:\n    vars:\n      VERSION:\n        sh: \"[ '{{.VERSION}}' != '' ] && echo '{{.VERSION}}' || svu\"\n    cmds:\n      - git checkout main\n      - git tag {{.VERSION}}\n      - git push --tags\n      - goreleaser --rm-dist\n      - defer: rm -rf dist\n    silent: true\n\n  unreleased:\n    desc: Prints the commits between main branch and latest version\n    vars:\n      VERSION:\n        sh: \"[ '{{.VERSION}}' != '' ] && echo '{{.VERSION}}' || curl -s https://api.github.com/repos/reposaur/reposaur/releases/latest | jq -r '.tag_name'\"\n    cmds:\n      - git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit main...{{.VERSION}}\n    silent: true\n"
  },
  {
    "path": "action.yml",
    "content": "name: Reposaur\nauthor: Reposaur Authors\ndescription: Audit your GitHub data using custom policies written in Rego\n\nbranding:\n  icon: lock\n  color: purple\n\ninputs:\n  version:\n    description: Version\n    default: main\n    required: false\n\nruns:\n  using: composite\n  steps:\n    - run: |\n        curl -o- https://raw.githubusercontent.com/reposaur/reposaur/${{ inputs.version }}/install.sh | bash\n        echo \"${{ github.action_path }}\" >> $GITHUB_PATH\n      working-directory: ${{ github.action_path }}\n      shell: bash\n"
  },
  {
    "path": "cmd/rsr/internal/bundle/bundle.go",
    "content": "package bundle\n\nimport (\n\t\"os\"\n\n\t\"github.com/reposaur/reposaur/cmd/rsr/internal/cmdutil\"\n\t\"github.com/reposaur/reposaur/pkg/sdk\"\n\t\"github.com/rs/zerolog\"\n\t\"github.com/spf13/cobra\"\n)\n\ntype bundleParams struct {\n\tpolicyPaths    []string\n\texperimental bool\n}\n\nfunc NewCmd() *cobra.Command {\n\tcmd := &cobra.Command{\n\t\tUse:   \"bundle [-p POLICY_PATH...] <OUTPUT>\",\n\t\tShort: \"Creates a bundle from the policies at POLICY_PATH (experimental)\",\n\t\tLong:  \"Creates a bundle from the policies at POLICY_PATH (experimental)\",\n\t}\n\n\tvar (\n\t\tparams = &bundleParams{}\n\t\tflags  = cmd.Flags()\n\t)\n\n\tcmdutil.AddPolicyPathsFlag(flags, &params.policyPaths)\n\tcmdutil.AddExperimentalFlag(flags, &params.experimental)\n\n\tcmd.Run = func(cmd *cobra.Command, args []string) {\n\t\tvar (\n\t\t\tctx    = cmd.Context()\n\t\t\tlogger = zerolog.Ctx(ctx)\n\t\t)\n\n\t\tif !params.experimental {\n\t\t\tlogger.Fatal().Msg(\"experimental feature, please use --experimental to accept\")\n\t\t}\n\n\t\tif len(args) != 1 {\n\t\t\tlogger.Fatal().Msgf(\"exactly 1 arguments required, got %d\", len(args))\n\t\t}\n\n\t\trsr, err := sdk.New(ctx, params.policyPaths, sdk.WithLogger(*logger))\n\t\tif err != nil {\n\t\t\tlogger.Fatal().Err(err).Msg(\"could not instantiate SDK\")\n\t\t}\n\n\t\tout, err := os.OpenFile(args[0], os.O_WRONLY+os.O_CREATE+os.O_TRUNC, 0o666)\n\t\tif err != nil {\n\t\t\tlogger.Fatal().Err(err).Msg(\"could not open file\")\n\t\t}\n\n\t\terr = rsr.Bundle(ctx, params.policyPaths, out)\n\t\tif err != nil {\n\t\t\tlogger.Fatal().Err(err).Msg(\"could not create bundle\")\n\t\t}\n\n\t\tlogger.Info().Msgf(\"bundle written to %s\", args[0])\n\t}\n\n\treturn cmd\n}\n"
  },
  {
    "path": "cmd/rsr/internal/cmdutil/env.go",
    "content": "package cmdutil\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strconv\"\n)\n\n// getEnv looks up every key in keys in the environment variables and returns\n// the first value found. If no value is found, returns an empty string.\nfunc getEnv(keys ...string) string {\n\tfor _, k := range keys {\n\t\tif v := os.Getenv(k); v != \"\" {\n\t\t\treturn v\n\t\t}\n\t}\n\n\treturn \"\"\n}\n\n// getInt64Env is similar to getEnv but converts the value to an int64. If no\n// value is found returns the zero-value for int64.\nfunc getInt64Env(keys ...string) int64 {\n\tval := getEnv(keys...)\n\n\tif val == \"\" {\n\t\treturn 0\n\t}\n\n\tintVal, err := strconv.ParseInt(val, 10, 0)\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"failed parsing env variable to int64: %w\", err))\n\t}\n\n\treturn intVal\n}\n"
  },
  {
    "path": "cmd/rsr/internal/cmdutil/flag.go",
    "content": "package cmdutil\n\nimport (\n\tgithubclient \"github.com/reposaur/reposaur/provider/github/client\"\n\t\"github.com/spf13/pflag\"\n)\n\ntype GitHubClientOptions struct {\n\t// GitHub API Base URL\n\tBaseURL string\n\n\t// GitHub Personal Access Token\n\tToken string\n\n\t// GitHub App ID\n\tAppID int64\n\n\t// GitHub App Private Key\n\tAppPrivateKey string\n\n\t// GitHub App Installation ID\n\tInstallationID int64\n}\n\nfunc AddPolicyPathsFlag(flags *pflag.FlagSet, p *[]string) {\n\tflags.StringSliceVarP(p, \"policy\", \"p\", []string{\".\"}, \"path to policy files or directories\")\n}\n\nfunc AddOutputFlag(flags *pflag.FlagSet, p *string) {\n\tflags.StringVarP(p, \"output\", \"o\", \"-\", \"output filename\")\n}\n\nfunc AddTraceFlag(flags *pflag.FlagSet, p *bool) {\n\tflags.BoolVarP(p, \"trace\", \"t\", false, \"enable tracing\")\n}\n\nfunc AddVerboseFlag(flags *pflag.FlagSet, p *bool) {\n\tflags.BoolVarP(p, \"verbose\", \"v\", false, \"print debug logs\")\n}\n\nfunc AddExperimentalFlag(flags *pflag.FlagSet, p *bool) {\n\tflags.BoolVar(p, \"experimental\", false, \"accepts the usage of experimental features\")\n}\n\nfunc AddGitHubFlags(flags *pflag.FlagSet, p *GitHubClientOptions) {\n\tvar (\n\t\tdefURL            = getEnv(\"GH_API_URL\", \"GITHUB_API_URL\")\n\t\tdefToken          = getEnv(\"GH_TOKEN\", \"GITHUB_TOKEN\")\n\t\tdefAppID          = getInt64Env(\"GH_APP_ID\", \"GITHUB_APP_ID\")\n\t\tdefAppPrivKey     = getEnv(\"GH_APP_PRIVATE_KEY\", \"GITHUB_APP_PRIVATE_KEY\")\n\t\tdefInstallationID = getInt64Env(\"GH_INSTALLATION_ID\", \"GITHUB_INSTALLATION_ID\")\n\t)\n\n\tif defURL == \"\" {\n\t\tdefURL = githubclient.DefaultBaseURL\n\t}\n\n\tflags.StringVar(&p.BaseURL, \"github-api-url\", defURL, \"base url GitHub API\")\n\tflags.StringVar(&p.Token, \"github-token\", defToken, \"token for GitHub\")\n\tflags.Int64Var(&p.AppID, \"github-app-id\", defAppID, \"id for GitHub App\")\n\tflags.StringVar(&p.AppPrivateKey, \"github-app-private-key\", defAppPrivKey, \"base64-encoded private key for GitHub App\")\n\tflags.Int64Var(&p.InstallationID, \"github-installation-id\", defInstallationID, \"installation ID for GitHub App\")\n}\n"
  },
  {
    "path": "cmd/rsr/internal/cmdutil/io.go",
    "content": "package cmdutil\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"os\"\n\n\t\"github.com/rs/zerolog\"\n)\n\n// GetInputReader returns an io.ReadCloser. If filename\n// is not empty, the file is opened and returned. Otherwise,\n// returns a reader from standard input.\nfunc GetInputReader(ctx context.Context, filename string) (r io.ReadCloser, err error) {\n\tvar (\n\t\tlogger = zerolog.Ctx(ctx)\n\t\tfile   = os.Stdin\n\t)\n\n\tif filename == \"\" || filename == \"-\" {\n\t\tlogger.Debug().Msg(\"using standard input as INPUT\")\n\t} else {\n\t\tlogger.Debug().Msgf(\"using %s as INPUT\", filename)\n\n\t\tfile, err = os.Open(filename)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn file, nil\n}\n\n// GetOutputWriter returns an io.WriteCloser. If filename\n// is not empty, the file is opened and returned. Otherwise,\n// returns a writer to standard output.\nfunc GetOutputWriter(ctx context.Context, filename string) (w io.WriteCloser, err error) {\n\tvar (\n\t\tlogger = zerolog.Ctx(ctx)\n\t\tfile   = os.Stdout\n\t)\n\n\tif filename == \"\" || filename == \"-\" {\n\t\tlogger.Debug().Msg(\"using standard output as OUTPUT\")\n\t} else {\n\t\tlogger.Debug().Msgf(\"using %s as OUTPUT\", filename)\n\n\t\tfile, err = os.OpenFile(filename, os.O_WRONLY+os.O_CREATE+os.O_TRUNC, 0o666)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn file, nil\n}\n"
  },
  {
    "path": "cmd/rsr/internal/cmdutil/logger.go",
    "content": "package cmdutil\n\nimport (\n\t\"os\"\n\n\t\"github.com/rs/zerolog\"\n)\n\n// NewLogger returns a new logger that outputs to\n// the standard error output. If verbose is true,\n// the log level will be `debug`, otherwise will be info.\nfunc NewLogger(verbose bool) zerolog.Logger {\n\tvar (\n\t\tlvl = zerolog.InfoLevel\n\t\tcw  = zerolog.ConsoleWriter{Out: os.Stderr}\n\t)\n\n\tif verbose {\n\t\tlvl = zerolog.DebugLevel\n\t}\n\n\treturn zerolog.New(cw).Level(lvl).With().Timestamp().Logger()\n}\n"
  },
  {
    "path": "cmd/rsr/internal/exec/exec.go",
    "content": "package exec\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"os\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/reposaur/reposaur/cmd/rsr/internal/cmdutil\"\n\t\"github.com/reposaur/reposaur/pkg/output\"\n\t\"github.com/reposaur/reposaur/pkg/sdk\"\n\t\"github.com/reposaur/reposaur/provider/github\"\n\tgithubclient \"github.com/reposaur/reposaur/provider/github/client\"\n\t\"github.com/rs/zerolog\"\n\t\"github.com/spf13/cobra\"\n)\n\ntype execParams struct {\n\tpolicyPaths    []string\n\toutputFilename string\n\tinputFilename  string\n\tenableTracing  bool\n\tgithub         cmdutil.GitHubClientOptions\n}\n\nfunc NewCmd() *cobra.Command {\n\tcmd := &cobra.Command{\n\t\tUse:   \"exec [-p POLICY_PATH...] [-n NAMESPACE] [-o OUTPUT] INPUT\",\n\t\tShort: \"Executes policies against INPUT data\",\n\t\tLong:  \"Executes policies against INPUT data\",\n\t}\n\n\tvar (\n\t\tparams = &execParams{}\n\t\tflags  = cmd.Flags()\n\t)\n\n\tcmdutil.AddOutputFlag(flags, &params.outputFilename)\n\tcmdutil.AddPolicyPathsFlag(flags, &params.policyPaths)\n\tcmdutil.AddTraceFlag(flags, &params.enableTracing)\n\tcmdutil.AddGitHubFlags(flags, &params.github)\n\n\tcmd.Run = func(cmd *cobra.Command, args []string) {\n\t\tvar (\n\t\t\tctx    = cmd.Context()\n\t\t\tlogger = zerolog.Ctx(ctx)\n\t\t)\n\n\t\tif len(args) > 1 {\n\t\t\tlogger.Fatal().Strs(\"args\", args).Msg(\"too many arguments for INPUT\")\n\t\t}\n\n\t\tif len(args) == 1 {\n\t\t\tparams.inputFilename = args[0]\n\t\t}\n\n\t\tinReader, err := cmdutil.GetInputReader(ctx, params.inputFilename)\n\t\tif err != nil {\n\t\t\tlogger.Fatal().Err(err).Msg(\"failed to get input reader\")\n\t\t}\n\t\tdefer func() {\n\t\t\tif err := inReader.Close(); err != nil {\n\t\t\t\tlogger.Fatal().Err(err).Msg(\"failed to close input reader\")\n\t\t\t}\n\t\t}()\n\n\t\toutWriter, err := cmdutil.GetOutputWriter(ctx, params.outputFilename)\n\t\tif err != nil {\n\t\t\tlogger.Fatal().Err(err).Msg(\"failed to get output writer\")\n\t\t}\n\t\tdefer func() {\n\t\t\tif err := outWriter.Close(); err != nil {\n\t\t\t\tlogger.Fatal().Err(err).Msg(\"failed to close output reader\")\n\t\t\t}\n\t\t}()\n\n\t\tgithubProvider, err := newGitHubProvider(ctx, &params.github)\n\t\tif err != nil {\n\t\t\tlogger.Fatal().Err(err).Msg(\"failed to create GitHub provider\")\n\t\t}\n\n\t\topts := []sdk.Option{\n\t\t\tsdk.WithLogger(*logger),\n\t\t\tsdk.WithProvider(githubProvider),\n\t\t\tsdk.WithTracingEnabled(params.enableTracing),\n\t\t}\n\n\t\trsr, err := sdk.New(ctx, params.policyPaths, opts...)\n\t\tif err != nil {\n\t\t\tlogger.Fatal().Err(err).Msg(\"could not instantiate SDK\")\n\t\t}\n\n\t\trunExec(ctx, rsr, inReader, outWriter)\n\t}\n\n\treturn cmd\n}\n\n// runExec will execute the policies against the data available\n// in inReader. The resulting reports will be outputted to outWriter.\nfunc runExec(ctx context.Context, rsr *sdk.Reposaur, inReader io.ReadCloser, outWriter io.WriteCloser) {\n\tstartTime := time.Now()\n\n\tvar (\n\t\tinputsCh = make(chan interface{})\n\t\tinputsWg = sync.WaitGroup{}\n\n\t\treportsCh = make(chan output.Report)\n\t\treportsWg = sync.WaitGroup{}\n\n\t\tlogger = zerolog.Ctx(ctx)\n\t)\n\n\t// Process inputs\n\tgo func() {\n\t\tfor input := range inputsCh {\n\t\t\tinputsWg.Done()\n\t\t\treportsWg.Add(1)\n\n\t\t\tgo func(input interface{}) {\n\t\t\t\tlogger.Debug().Msg(\"processing input\")\n\n\t\t\t\treport, err := rsr.Check(ctx, input)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlogger.Fatal().Err(err).Send()\n\t\t\t\t}\n\n\t\t\t\tlogger.Debug().Msg(\"done processing input\")\n\n\t\t\t\treportsCh <- report\n\t\t\t}(input)\n\t\t}\n\t}()\n\n\t// Output reports\n\tgo func() {\n\t\tenc := json.NewEncoder(outWriter)\n\t\tenc.SetIndent(\"\", \"  \")\n\n\t\tfor report := range reportsCh {\n\t\t\tsarif, err := output.NewSarifReport(report)\n\t\t\tif err != nil {\n\t\t\t\tlogger.Fatal().Err(err).Send()\n\t\t\t}\n\n\t\t\tif err := enc.Encode(sarif); err != nil {\n\t\t\t\tlogger.Fatal().Err(err).Send()\n\t\t\t}\n\n\t\t\treportsWg.Done()\n\t\t}\n\t}()\n\n\t// Start processing inputs\n\tdec := json.NewDecoder(inReader)\n\n\tfor {\n\t\tvar input interface{}\n\n\t\tif err := dec.Decode(&input); errors.Is(err, io.EOF) {\n\t\t\tbreak\n\t\t} else if err != nil {\n\t\t\tlogger.Fatal().Err(err).Msg(\"failed to decode input\")\n\t\t}\n\n\t\tswitch inputT := input.(type) {\n\t\tcase map[string]interface{}:\n\t\t\tlogger.Debug().Msg(\"received 1 input\")\n\n\t\t\tinputsWg.Add(1)\n\t\t\tinputsCh <- inputT\n\n\t\tcase []interface{}:\n\t\t\tlogger.Debug().Msgf(\"received %d inputs\", len(inputT))\n\n\t\t\tfor _, input := range inputT {\n\t\t\t\tinputsWg.Add(1)\n\t\t\t\tinputsCh <- input\n\t\t\t}\n\t\t}\n\t}\n\n\tinputsWg.Wait()\n\tclose(inputsCh)\n\tlogger.Debug().Msg(\"closed inputs channel\")\n\n\treportsWg.Wait()\n\tclose(reportsCh)\n\tlogger.Debug().Msg(\"closed reports channel\")\n\n\tlogger.Info().Dur(\"timeElapsed\", time.Since(startTime)).Msg(\"done\")\n\n\t// TODO: should exit with 1 if there are failed results\n\tos.Exit(0)\n}\n\nfunc newGitHubProvider(ctx context.Context, opts *cmdutil.GitHubClientOptions) (*github.GitHub, error) {\n\tvar client *githubclient.Client\n\n\tif opts.AppID != 0 && opts.InstallationID != 0 && opts.AppPrivateKey != \"\" {\n\t\tappClient, err := githubclient.NewAppClient(ctx, opts.BaseURL, opts.AppID, opts.InstallationID, []byte(opts.AppPrivateKey))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tclient = appClient\n\t} else if opts.Token != \"\" {\n\t\tclient = githubclient.NewTokenClient(ctx, opts.Token)\n\t}\n\n\treturn github.NewProvider(client), nil\n}\n"
  },
  {
    "path": "cmd/rsr/internal/root/root.go",
    "content": "package root\n\nimport (\n\t\"github.com/reposaur/reposaur/cmd/rsr/internal/bundle\"\n\t\"github.com/reposaur/reposaur/cmd/rsr/internal/cmdutil\"\n\t\"github.com/reposaur/reposaur/cmd/rsr/internal/exec\"\n\t\"github.com/reposaur/reposaur/cmd/rsr/internal/test\"\n\t\"github.com/reposaur/reposaur/internal/build\"\n\t\"github.com/spf13/cobra\"\n)\n\ntype rootParams struct {\n\tverbose bool\n}\n\nfunc NewCmd() *cobra.Command {\n\tcmd := &cobra.Command{\n\t\tVersion: build.Version,\n\t\tUse:     \"rsr\",\n\t\tShort:   \"Reposaur - security & compliance for GitHub metadata\",\n\t}\n\n\tparams := &rootParams{}\n\n\tcmdutil.AddVerboseFlag(cmd.PersistentFlags(), &params.verbose)\n\n\tcmd.PersistentPreRun = func(cmd *cobra.Command, args []string) {\n\t\tlogger := cmdutil.NewLogger(params.verbose)\n\n\t\tcmd.SetContext(\n\t\t\tlogger.WithContext(cmd.Context()),\n\t\t)\n\t}\n\n\tcmd.AddCommand(\n\t\texec.NewCmd(),\n\t\ttest.NewCmd(),\n\t\tbundle.NewCmd(),\n\t)\n\n\treturn cmd\n}\n"
  },
  {
    "path": "cmd/rsr/internal/test/test.go",
    "content": "package test\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/reposaur/reposaur/cmd/rsr/internal/cmdutil\"\n\t\"github.com/reposaur/reposaur/pkg/sdk\"\n\t\"github.com/rs/zerolog\"\n\t\"github.com/spf13/cobra\"\n)\n\ntype testParams struct {\n\tpolicyPaths    []string\n\toutputFilename string\n\tenableTracing  bool\n}\n\nfunc NewCmd() *cobra.Command {\n\tcmd := &cobra.Command{\n\t\tUse:   \"test POLICY_PATH...\",\n\t\tShort: \"Runs the tests available in POLICY_PATH\",\n\t\tLong:  \"Runs the tests available in POLICY_PATH\",\n\t}\n\n\tvar (\n\t\tparams = &testParams{policyPaths: []string{\".\"}}\n\t\tflags  = cmd.Flags()\n\t)\n\n\tcmdutil.AddOutputFlag(flags, &params.outputFilename)\n\tcmdutil.AddTraceFlag(flags, &params.enableTracing)\n\n\tcmd.Run = func(cmd *cobra.Command, args []string) {\n\t\tvar (\n\t\t\tctx    = cmd.Context()\n\t\t\tlogger = zerolog.Ctx(ctx)\n\t\t)\n\n\t\topts := []sdk.Option{\n\t\t\tsdk.WithLogger(*logger),\n\t\t\tsdk.WithTracingEnabled(params.enableTracing),\n\t\t}\n\n\t\tif len(args) > 0 {\n\t\t\tparams.policyPaths = args\n\t\t}\n\n\t\trsr, err := sdk.New(ctx, params.policyPaths, opts...)\n\t\tif err != nil {\n\t\t\tlogger.Fatal().Err(err).Msg(\"could not instantiate SDK\")\n\t\t}\n\n\t\trunTest(ctx, rsr)\n\t}\n\n\treturn cmd\n}\n\n// runTest executes policy tests, outputting the results\n// to the provided  outWriter.\n//\n// If any test fails, the function will exit with code 1.\n// Otherwise, exits with code 0.\nfunc runTest(ctx context.Context, rsr *sdk.Reposaur) {\n\tvar (\n\t\tstartTime = time.Now()\n\t\tlogger    = zerolog.Ctx(ctx)\n\t)\n\n\tresults, err := rsr.Test(ctx)\n\tif err != nil {\n\t\tlogger.Fatal().Err(err).Msg(\"failed to execute tests\")\n\t}\n\n\tvar failedTests, totalTests int\n\n\tfor _, r := range results {\n\t\ttotalTests++\n\n\t\tif r.Fail {\n\t\t\tfailedTests++\n\t\t\tlogger.Error().Msg(r.String())\n\t\t} else {\n\t\t\tlogger.Info().Msg(r.String())\n\t\t}\n\t}\n\n\ttestLogger := logger.With().\n\t\tInt(\"passed\", totalTests-failedTests).\n\t\tInt(\"failed\", failedTests).\n\t\tInt(\"total\", totalTests).\n\t\tDur(\"timeElapsed\", time.Since(startTime)).\n\t\tLogger()\n\n\tif failedTests > 0 {\n\t\ttestLogger.Error().Msg(\"done\")\n\t\tos.Exit(1)\n\t}\n\n\ttestLogger.Info().Msg(\"done\")\n\tos.Exit(0)\n}\n"
  },
  {
    "path": "cmd/rsr/rsr.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/reposaur/reposaur/cmd/rsr/internal/root\"\n)\n\nfunc main() {\n\tif err := root.NewCmd().Execute(); err != nil {\n\t\tif _, err := fmt.Fprintln(os.Stderr, err); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tos.Exit(1)\n\t}\n}\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/reposaur/reposaur\n\ngo 1.18\n\nrequire (\n\tgithub.com/bradleyfalzon/ghinstallation/v2 v2.1.0\n\tgithub.com/hashicorp/go-retryablehttp v0.7.2\n\tgithub.com/open-policy-agent/opa v0.48.0\n\tgithub.com/owenrumney/go-sarif/v2 v2.1.2\n\tgithub.com/rs/zerolog v1.28.0\n\tgithub.com/spf13/cobra v1.6.1\n\tgithub.com/spf13/pflag v1.0.5\n\tgolang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5\n)\n\nrequire (\n\tgithub.com/OneOfOne/xxhash v1.2.8 // indirect\n\tgithub.com/agnivade/levenshtein v1.1.1 // indirect\n\tgithub.com/ghodss/yaml v1.0.0 // indirect\n\tgithub.com/gobwas/glob v0.2.3 // indirect\n\tgithub.com/golang-jwt/jwt/v4 v4.4.1 // indirect\n\tgithub.com/golang/protobuf v1.5.2 // indirect\n\tgithub.com/google/go-github/v45 v45.2.0 // indirect\n\tgithub.com/google/go-querystring v1.1.0 // indirect\n\tgithub.com/hashicorp/go-cleanhttp v0.5.2 // indirect\n\tgithub.com/inconshreveable/mousetrap v1.0.1 // indirect\n\tgithub.com/mattn/go-colorable v0.1.12 // indirect\n\tgithub.com/mattn/go-isatty v0.0.14 // indirect\n\tgithub.com/pkg/errors v0.9.1 // indirect\n\tgithub.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect\n\tgithub.com/tchap/go-patricia/v2 v2.3.1 // indirect\n\tgithub.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect\n\tgithub.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect\n\tgithub.com/yashtewari/glob-intersection v0.1.0 // indirect\n\tgolang.org/x/crypto v0.4.0 // indirect\n\tgolang.org/x/net v0.5.0 // indirect\n\tgolang.org/x/sys v0.4.0 // indirect\n\tgoogle.golang.org/appengine v1.6.7 // indirect\n\tgoogle.golang.org/protobuf v1.28.1 // indirect\n\tgopkg.in/yaml.v2 v2.4.0 // indirect\n)\n"
  },
  {
    "path": "go.sum",
    "content": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=\ncloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=\ncloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=\ncloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=\ncloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=\ncloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=\ncloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=\ncloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=\ncloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=\ncloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=\ncloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=\ncloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=\ncloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=\ncloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=\ncloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=\ncloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=\ncloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=\ncloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=\ncloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=\ncloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=\ncloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=\ncloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=\ncloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=\ncloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=\ncloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=\ncloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=\ncloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=\ncloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=\ncloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=\ncloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=\ndmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=\ngithub.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=\ngithub.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=\ngithub.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=\ngithub.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=\ngithub.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=\ngithub.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=\ngithub.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=\ngithub.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=\ngithub.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=\ngithub.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=\ngithub.com/bradleyfalzon/ghinstallation/v2 v2.1.0 h1:5+NghM1Zred9Z078QEZtm28G/kfDfZN/92gkDlLwGVA=\ngithub.com/bradleyfalzon/ghinstallation/v2 v2.1.0/go.mod h1:Xg3xPRN5Mcq6GDqeUVhFbjEWMb4JHCyWEeeBGEYQoTU=\ngithub.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA=\ngithub.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=\ngithub.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=\ngithub.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=\ngithub.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=\ngithub.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=\ngithub.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=\ngithub.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=\ngithub.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=\ngithub.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg=\ngithub.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8=\ngithub.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g=\ngithub.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=\ngithub.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=\ngithub.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=\ngithub.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=\ngithub.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=\ngithub.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=\ngithub.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=\ngithub.com/foxcpp/go-mockdns v0.0.0-20210729171921-fb145fc6f897 h1:E52jfcE64UG42SwLmrW0QByONfGynWuzBvm86BoB9z8=\ngithub.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=\ngithub.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=\ngithub.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=\ngithub.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=\ngithub.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=\ngithub.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=\ngithub.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=\ngithub.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=\ngithub.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=\ngithub.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ=\ngithub.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=\ngithub.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=\ngithub.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=\ngithub.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=\ngithub.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=\ngithub.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=\ngithub.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=\ngithub.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=\ngithub.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=\ngithub.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=\ngithub.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=\ngithub.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=\ngithub.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=\ngithub.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=\ngithub.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=\ngithub.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=\ngithub.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=\ngithub.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=\ngithub.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=\ngithub.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=\ngithub.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=\ngithub.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=\ngithub.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=\ngithub.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=\ngithub.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=\ngithub.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=\ngithub.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=\ngithub.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw=\ngithub.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=\ngithub.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=\ngithub.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/go-github/v45 v45.2.0 h1:5oRLszbrkvxDDqBCNj2hjDZMKmvexaZ1xw/FCD+K3FI=\ngithub.com/google/go-github/v45 v45.2.0/go.mod h1:FObaZJEDSTa/WGCzZ2Z3eoCDXWJKMenWWTrd8jrta28=\ngithub.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=\ngithub.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=\ngithub.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=\ngithub.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=\ngithub.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=\ngithub.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=\ngithub.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=\ngithub.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=\ngithub.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=\ngithub.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=\ngithub.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=\ngithub.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=\ngithub.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=\ngithub.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0=\ngithub.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=\ngithub.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=\ngithub.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=\ngithub.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=\ngithub.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=\ngithub.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=\ngithub.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=\ngithub.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=\ngithub.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=\ngithub.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=\ngithub.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=\ngithub.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=\ngithub.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=\ngithub.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=\ngithub.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=\ngithub.com/open-policy-agent/opa v0.48.0 h1:s2K823yohAUu/HB4MOPWDhBh88JMKQv7uTr6S89fbM0=\ngithub.com/open-policy-agent/opa v0.48.0/go.mod h1:CsQcksP+qGBxO9oEBj1NnZqKcjgjmTJbRNTzjZB/DXQ=\ngithub.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U=\ngithub.com/owenrumney/go-sarif/v2 v2.1.2 h1:PMDK7tXShJ9zsB7bfvlpADH5NEw1dfA9xwU8Xtdj73U=\ngithub.com/owenrumney/go-sarif/v2 v2.1.2/go.mod h1:MSqMMx9WqlBSY7pXoOZWgEsVB4FDNfhcaXDA1j6Sr+w=\ngithub.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=\ngithub.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=\ngithub.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=\ngithub.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=\ngithub.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=\ngithub.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ=\ngithub.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=\ngithub.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=\ngithub.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=\ngithub.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY=\ngithub.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=\ngithub.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=\ngithub.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=\ngithub.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=\ngithub.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=\ngithub.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngithub.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=\ngithub.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes=\ngithub.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=\ngithub.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=\ngithub.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=\ngithub.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=\ngithub.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=\ngithub.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=\ngithub.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=\ngithub.com/yashtewari/glob-intersection v0.1.0 h1:6gJvMYQlTDOL3dMsPF6J0+26vwX9MB8/1q3uAdhmTrg=\ngithub.com/yashtewari/glob-intersection v0.1.0/go.mod h1:LK7pIC3piUjovexikBbJ26Yml7g8xa5bsjfx2v1fwok=\ngithub.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=\ngo.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=\ngo.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=\ngo.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=\ngo.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=\ngo.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=\ngo.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=\ngolang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=\ngolang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=\ngolang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=\ngolang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=\ngolang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=\ngolang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=\ngolang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=\ngolang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=\ngolang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=\ngolang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=\ngolang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=\ngolang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=\ngolang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=\ngolang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=\ngolang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=\ngolang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=\ngolang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=\ngolang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=\ngolang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=\ngolang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=\ngolang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=\ngolang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=\ngolang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=\ngolang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=\ngolang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=\ngolang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=\ngolang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=\ngolang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=\ngolang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=\ngolang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=\ngolang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 h1:OSnWWcOd/CtWQC2cYSBgbTSJv3ciqd8r54ySIW2y3RE=\ngolang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=\ngolang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=\ngolang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=\ngolang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=\ngolang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=\ngolang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=\ngolang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=\ngolang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=\ngolang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=\ngolang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=\ngolang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=\ngolang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=\ngolang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngoogle.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=\ngoogle.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=\ngoogle.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=\ngoogle.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=\ngoogle.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=\ngoogle.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=\ngoogle.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=\ngoogle.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=\ngoogle.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=\ngoogle.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=\ngoogle.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=\ngoogle.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=\ngoogle.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=\ngoogle.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=\ngoogle.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=\ngoogle.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=\ngoogle.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=\ngoogle.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=\ngoogle.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=\ngoogle.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=\ngoogle.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=\ngoogle.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=\ngoogle.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=\ngoogle.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=\ngoogle.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=\ngoogle.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=\ngoogle.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=\ngoogle.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=\ngoogle.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=\ngoogle.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=\ngoogle.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=\ngoogle.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=\ngoogle.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=\ngoogle.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=\ngoogle.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=\ngoogle.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=\ngoogle.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=\ngoogle.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=\ngoogle.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=\ngoogle.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=\ngoogle.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=\ngoogle.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=\ngoogle.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=\ngoogle.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=\ngoogle.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=\ngoogle.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=\ngoogle.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=\ngopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=\ngopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\nhonnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=\nhonnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=\nhonnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=\nrsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=\nrsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=\nrsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=\n"
  },
  {
    "path": "install.sh",
    "content": "#!/bin/sh\nset -e\n\nRELEASES_URL=\"https://github.com/reposaur/reposaur/releases\"\nFILE_BASENAME=\"reposaur\"\n\ntest -z \"$VERSION\" && VERSION=\"$(curl -sfL -o /dev/null -w %{url_effective} \"$RELEASES_URL/latest\" |\n  rev |\n  cut -f1 -d'/' |\n  rev)\"\n\ntest -z \"$VERSION\" && {\n  echo \"Unable to get Reposaur version.\" >&2\n  exit 1\n}\n\ntest -z \"$TEMP_DIR\" && TEMP_DIR=\"$(mktemp -d)\"\ntest -z \"$INSTALLATION_DIR\" && INSTALLATION_DIR=\"${HOME}/.reposaur\"\n\nmkdir -p \"${INSTALLATION_DIR}/bin\"\n\nexport TAR_FILE=\"$TEMP_DIR/${FILE_BASENAME}_$(uname -s)_$(uname -m).tar.gz\"\n\necho \"Downloading Reposaur ${VERSION}...\"\ncurl -sfLo \"$TAR_FILE\" \\\n  \"$RELEASES_URL/download/${VERSION}/${FILE_BASENAME}_${VERSION#v}_$(uname -s)_$(uname -m).tar.gz\"\n\necho \"\"\necho \"Installing Reposaur to ${INSTALLATION_DIR}...\"\ntar -xf \"${TAR_FILE}\" -C \"${INSTALLATION_DIR}\"\nmv \"${INSTALLATION_DIR}/rsr\" \"${INSTALLATION_DIR}/bin\"\n\n# This binary will be deprecated soon\nmv \"${INSTALLATION_DIR}/reposaur\" \"${INSTALLATION_DIR}/bin\"\n\necho \"\"\necho \"Done, try running:\"\necho \"\\t${INSTALLATION_DIR}/bin/rsr --help\"\necho \"\"\necho \"It's recommended to add the bin directory to your PATH:\"\necho \"\\tPATH=\\\"\\$PATH:${INSTALLATION_DIR}/bin\\\"\"\n"
  },
  {
    "path": "internal/build/build.go",
    "content": "package build\n\nimport (\n\t\"runtime/debug\"\n)\n\n// Version is dynamically set by the toolchain.\nvar Version = \"DEV\"\n\nfunc init() {\n\tif Version == \"DEV\" {\n\t\tif info, ok := debug.ReadBuildInfo(); ok && info.Main.Version != \"(devel)\" {\n\t\t\tVersion = info.Main.Version\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/policy/engine.go",
    "content": "package policy\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/open-policy-agent/opa/ast\"\n\t\"github.com/open-policy-agent/opa/bundle\"\n\t\"github.com/open-policy-agent/opa/loader\"\n\t\"github.com/open-policy-agent/opa/rego\"\n\t\"github.com/open-policy-agent/opa/topdown\"\n\t\"github.com/reposaur/reposaur/pkg/output\"\n)\n\ntype Option func(*Engine)\n\ntype Engine struct {\n\tmodules       map[string]*ast.Module\n\tcompiler      *ast.Compiler\n\tenableTracing bool\n}\n\nfunc Load(_ context.Context, policyPaths []string, opts ...Option) (*Engine, error) {\n\tpolicies, err := loader.NewFileLoader().\n\t\tWithProcessAnnotation(true).\n\t\tFiltered(policyPaths, isRegoFile)\n\tif err != nil {\n\t\treturn nil, &ErrPolicyLoad{err}\n\t}\n\n\tif len(policies.Modules) == 0 {\n\t\treturn nil, &ErrNoPolicies{policyPaths}\n\t}\n\n\tmodules := policies.ParsedModules()\n\tcompiler := ast.NewCompiler().WithEnablePrintStatements(true)\n\n\tcompiler.Compile(modules)\n\n\tif compiler.Failed() {\n\t\treturn nil, fmt.Errorf(\"compiler: %w\", compiler.Errors)\n\t}\n\n\tengine := &Engine{\n\t\tmodules:  modules,\n\t\tcompiler: compiler,\n\t}\n\n\tfor _, opt := range opts {\n\t\topt(engine)\n\t}\n\n\treturn engine, nil\n}\n\n// WithTracingEnabled enables or disables policy\n// execution tracing.\nfunc WithTracingEnabled(enabled bool) Option {\n\treturn func(e *Engine) {\n\t\te.enableTracing = enabled\n\t}\n}\n\n// Namespaces returns all the namespaces in the engine.\nfunc (e *Engine) Namespaces() []string {\n\tvar namespaces []string\n\tfor _, module := range e.Modules() {\n\t\tnamespace := strings.Replace(module.Package.Path.String(), \"data.\", \"\", 1)\n\t\tfor _, ns := range namespaces {\n\t\t\tif ns == namespace {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\tnamespaces = append(namespaces, namespace)\n\t}\n\n\treturn namespaces\n}\n\n// Compiler returns the compiler from the loaded policies.\nfunc (e *Engine) Compiler() *ast.Compiler {\n\treturn e.compiler\n}\n\n// Modules returns the modules from the loaded policies.\nfunc (e *Engine) Modules() map[string]*ast.Module {\n\treturn e.modules\n}\n\nfunc (e *Engine) Check(ctx context.Context, namespace string, input interface{}) (output.Report, error) {\n\treport, err := e.check(ctx, namespace, input)\n\tif err != nil {\n\t\treturn output.Report{}, fmt.Errorf(\"check: %w\", err)\n\t}\n\n\treturn report, nil\n}\n\nfunc (e *Engine) check(ctx context.Context, namespace string, input interface{}) (output.Report, error) {\n\treport := output.Report{\n\t\tRules:   map[string]*output.Rule{},\n\t\tResults: map[string]*output.Result{},\n\t}\n\n\tfor _, mod := range e.Modules() {\n\t\tcurrNamespace := strings.TrimPrefix(mod.Package.Path.String(), \"data.\")\n\t\tif currNamespace != namespace {\n\t\t\tcontinue\n\t\t}\n\n\t\tfor _, r := range mod.Rules {\n\t\t\tvar annotations *ast.Annotations\n\t\t\tfor _, a := range mod.Annotations {\n\t\t\t\tif a.Scope == \"rule\" && a.GetTargetPath().String() == r.Ref().String() {\n\t\t\t\t\tannotations = a\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trule, err := output.NewRule(namespace, r, annotations)\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\treport.AddRule(rule)\n\t\t}\n\t}\n\n\tfor _, rule := range report.Rules {\n\t\tvar result *output.Result\n\n\t\tresult, err := e.querySkip(ctx, rule, input)\n\t\tif err != nil {\n\t\t\treturn output.Report{}, fmt.Errorf(\"query skip rule: %s: %w\", rule.UID(), err)\n\t\t}\n\n\t\tif !result.Skipped {\n\t\t\tresult, err = e.queryRule(ctx, rule, input)\n\t\t\tif err != nil {\n\t\t\t\treturn output.Report{}, fmt.Errorf(\"query rule: %s: %w\", rule.UID(), err)\n\t\t\t}\n\t\t}\n\n\t\treport.AddResult(result)\n\t}\n\n\treturn report, nil\n}\n\nfunc (e *Engine) queryRule(ctx context.Context, rule *output.Rule, input interface{}) (*output.Result, error) {\n\tquery := fmt.Sprintf(\"data.%s.%s_%s\", rule.Namespace, rule.Kind, rule.ID)\n\tregoInstance := e.buildRegoInstance(query, input)\n\n\tresultSet, err := regoInstance.Eval(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"query eval: %w\", err)\n\t}\n\n\tresult := output.Result{\n\t\tRule:   rule,\n\t\tQuery:  query,\n\t\tPassed: len(resultSet) == 0,\n\t}\n\n\treturn &result, nil\n}\n\nfunc (e *Engine) querySkip(ctx context.Context, rule *output.Rule, input interface{}) (*output.Result, error) {\n\tquery := fmt.Sprintf(\"data.%s.skip[_][_] == %q\", rule.Namespace, rule.ID)\n\tregoInstance := e.buildRegoInstance(query, input)\n\n\tresultSet, err := regoInstance.Eval(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"skip query eval: %w\", err)\n\t}\n\n\tresult := output.Result{\n\t\tRule:    rule,\n\t\tQuery:   query,\n\t\tSkipped: len(resultSet) > 0,\n\t}\n\n\treturn &result, nil\n}\n\nfunc (e *Engine) buildRegoInstance(query string, input interface{}) *rego.Rego {\n\treturn rego.New(\n\t\trego.Query(query),\n\t\trego.Input(input),\n\t\trego.Compiler(e.compiler),\n\t\trego.Trace(e.enableTracing),\n\t\trego.StrictBuiltinErrors(true),\n\t\trego.PrintHook(topdown.NewPrintHook(os.Stderr)),\n\t)\n}\n\nfunc isRegoFile(_ string, info os.FileInfo, _ int) bool {\n\treturn !info.IsDir() && !strings.HasSuffix(info.Name(), bundle.RegoExt)\n}\n"
  },
  {
    "path": "internal/policy/errors.go",
    "content": "package policy\n\nimport \"fmt\"\n\ntype ErrPolicyLoad struct {\n\tloaderError error\n}\n\nfunc (e *ErrPolicyLoad) Error() string {\n\treturn fmt.Sprintf(\"load: %v\", e.loaderError)\n}\n\ntype ErrNoPolicies struct {\n\tpolicyPaths []string\n}\n\nfunc (e *ErrNoPolicies) Error() string {\n\treturn fmt.Sprintf(\"no policy .rego files found in %v\", e.policyPaths)\n}\n"
  },
  {
    "path": "pkg/output/report.go",
    "content": "package output\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/open-policy-agent/opa/ast\"\n)\n\ntype Severity string\n\nconst (\n\tErrorSeverity   = \"error\"\n\tWarningSeverity = \"warning\"\n\tNoteSeverity    = \"note\"\n)\n\nvar SeverityRuleMap = map[string][]string{\n\tErrorSeverity:   {\"error\", \"fail\", \"violation\"},\n\tWarningSeverity: {\"warn\"},\n\tNoteSeverity:    {\"note\", \"info\"},\n}\n\nvar SecuritySeverityMap = map[string]string{\n\tErrorSeverity:   \"7\",\n\tWarningSeverity: \"4\",\n\tNoteSeverity:    \"1\",\n}\n\ntype Report struct {\n\tRules      map[string]*Rule   `json:\"rules\"`\n\tResults    map[string]*Result `json:\"results\"`\n\tRuleCount  int                `json:\"ruleCount\"`\n\tProperties ReportProperties   `json:\"properties\"`\n}\n\nfunc (r *Report) AddRule(rule *Rule) {\n\tr.RuleCount++\n\tr.Rules[rule.UID()] = rule\n}\n\nfunc (r *Report) AddResult(result *Result) {\n\tr.Results[result.Rule.UID()] = result\n}\n\ntype ReportProperties map[string]interface{}\n\ntype Result struct {\n\tRule    *Rule  `json:\"rule\"`\n\tQuery   string `json:\"query\"`\n\tSkipped bool   `json:\"skipped\"`\n\tPassed  bool   `json:\"passed\"`\n}\n\ntype Rule struct {\n\tID               string   `json:\"id\"`\n\tTitle            string   `json:\"title\"`\n\tKind             string   `json:\"kind\"`\n\tSeverity         string   `json:\"severity\"`\n\tSecuritySeverity string   `json:\"security-severity\"`\n\tDescription      string   `json:\"description\"`\n\tNamespace        string   `json:\"namespace\"`\n\tTags             []string `json:\"tags\"`\n}\n\nfunc NewRule(namespace string, rule *ast.Rule, as *ast.Annotations) (*Rule, error) {\n\theadSplit := strings.SplitN(rule.Head.Name.String(), \"_\", 2)\n\n\tif len(headSplit) != 2 {\n\t\treturn nil, fmt.Errorf(\"new rule: parse id: invalid rule name: %s\", rule.Head.Name.String())\n\t}\n\n\tvar (\n\t\tkind     = headSplit[0]\n\t\tid       = headSplit[1]\n\t\tseverity = \"\"\n\t)\n\n\tfor sev, kinds := range SeverityRuleMap {\n\t\tfor _, k := range kinds {\n\t\t\tif k == kind {\n\t\t\t\tseverity = sev\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif severity != \"\" {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif severity == \"\" {\n\t\treturn nil, fmt.Errorf(\"new rule: could not find severity for %s\", kind)\n\t}\n\n\tr := Rule{\n\t\tID:               id,\n\t\tTitle:            id,\n\t\tKind:             kind,\n\t\tSeverity:         severity,\n\t\tSecuritySeverity: SecuritySeverityMap[severity],\n\t\tNamespace:        namespace,\n\t}\n\n\tif as != nil {\n\t\tif as.Title != \"\" {\n\t\t\tr.Title = as.Title\n\t\t} else {\n\t\t\tr.Title = r.ID\n\t\t}\n\n\t\tif as.Description != \"\" {\n\t\t\tr.Description = as.Description\n\t\t} else {\n\t\t\tr.Description = r.Title\n\t\t}\n\n\t\tif tags, ok := as.Custom[\"tags\"]; ok {\n\t\t\tfor _, t := range tags.([]interface{}) {\n\t\t\t\tr.Tags = append(r.Tags, t.(string))\n\t\t\t}\n\t\t}\n\n\t\tif secSev, ok := as.Custom[\"security-severity\"]; ok {\n\t\t\tr.SecuritySeverity = fmt.Sprintf(\"%v\", secSev)\n\t\t}\n\t}\n\n\treturn &r, nil\n}\n\nfunc (r Rule) CausesFailure() bool {\n\treturn r.Severity == ErrorSeverity\n}\n\nfunc (r Rule) UID() string {\n\treturn fmt.Sprintf(\"%s/%s/%s\", r.Namespace, r.Kind, r.ID)\n}\n"
  },
  {
    "path": "pkg/output/sarif.go",
    "content": "package output\n\nimport (\n\t\"strings\"\n\n\t\"github.com/owenrumney/go-sarif/v2/sarif\"\n)\n\nfunc NewSarifReport(report Report) (*sarif.Report, error) {\n\tsr, err := sarif.New(sarif.Version210)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\trun := sarif.NewRunWithInformationURI(\"Reposaur\", \"https://github.com/reposaur/reposaur\")\n\n\trun.Properties = sarif.Properties{}\n\tfor k, v := range report.Properties {\n\t\trun.Properties[k] = v\n\t}\n\n\tfor _, rule := range report.Rules {\n\t\tprops := sarif.Properties{}\n\n\t\tif len(rule.Tags) > 0 {\n\t\t\tprops[\"tags\"] = rule.Tags\n\t\t}\n\n\t\tif rule.SecuritySeverity != \"\" {\n\t\t\tprops[\"security-severity\"] = rule.SecuritySeverity\n\t\t}\n\n\t\trun.AddRule(rule.UID()).\n\t\t\tWithName(rule.Title).\n\t\t\tWithDescription(rule.Title).\n\t\t\tWithFullDescription(\n\t\t\t\tsarif.NewMultiformatMessageString(rule.Description).\n\t\t\t\t\tWithMarkdown(rule.Description),\n\t\t\t).\n\t\t\tWithMarkdownHelp(rule.Description).\n\t\t\tWithProperties(props)\n\t}\n\n\tfor _, result := range report.Results {\n\t\tif !result.Passed && !result.Skipped {\n\t\t\trun.AddResult(sarif.NewRuleResult(result.Rule.UID()).\n\t\t\t\tWithLevel(strings.ToLower(result.Rule.Severity)).\n\t\t\t\tWithMessage(sarif.NewTextMessage(result.Rule.Title)).\n\t\t\t\tWithLocations([]*sarif.Location{\n\t\t\t\t\tsarif.NewLocation().WithPhysicalLocation(\n\t\t\t\t\t\tsarif.NewPhysicalLocation().\n\t\t\t\t\t\t\tWithArtifactLocation(\n\t\t\t\t\t\t\t\tsarif.NewSimpleArtifactLocation(\".\"),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t)\n\t\t}\n\t}\n\n\tsr.AddRun(run)\n\n\treturn sr, nil\n}\n"
  },
  {
    "path": "pkg/sdk/sdk.go",
    "content": "package sdk\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/open-policy-agent/opa/compile\"\n\t\"github.com/open-policy-agent/opa/rego\"\n\t\"github.com/open-policy-agent/opa/tester\"\n\t\"github.com/open-policy-agent/opa/topdown\"\n\t\"github.com/reposaur/reposaur/internal/policy\"\n\t\"github.com/reposaur/reposaur/pkg/output\"\n\t\"github.com/reposaur/reposaur/provider\"\n\t\"github.com/reposaur/reposaur/provider/github\"\n\n\t\"github.com/rs/zerolog\"\n)\n\nvar DefaultProviders = []provider.Provider{\n\tgithub.NewProvider(nil),\n}\n\n// Option represents a Reposaur option that can change a\n// particular behavior.\ntype Option func(*Reposaur)\n\n// Reposaur represents an instance of the auditing engine. It can be\n// started with several options that control configuration, logging and\n// the client to GitHub.\ntype Reposaur struct {\n\tlogger        zerolog.Logger\n\tengine        *policy.Engine\n\tproviders     []provider.Provider\n\tenableTracing bool\n}\n\n// New returns a new Reposaur instance, loading and\n// compiling any policies provided and registering\n// the built-in functions.\n//\n// If an HTTP client isn't passed as an option, a default\n// client is created. A default (unauthenticated) client is created\n// using `util.GitHubTransport`.\n//\n// The util functions available in the `util` package can be used to\n// create authenticated HTTP clients.\n//\n// The default HTTP client will use the default host `api.github.com`. Can\n// be customized using the `GITHUB_HOST` or `GH_HOST` environment variables.\nfunc New(ctx context.Context, policyPaths []string, opts ...Option) (*Reposaur, error) {\n\tsdk := &Reposaur{\n\t\tlogger: zerolog.New(os.Stderr),\n\t}\n\n\tfor _, opt := range opts {\n\t\topt(sdk)\n\t}\n\n\tif len(sdk.providers) == 0 {\n\t\tsdk.providers = DefaultProviders\n\t}\n\n\tfor _, p := range sdk.providers {\n\t\tfor _, b := range p.Builtins() {\n\t\t\trego.RegisterBuiltinDyn(b.Func(), b.Impl)\n\t\t}\n\t}\n\n\tvar err error\n\tsdk.engine, err = policy.Load(ctx, policyPaths, policy.WithTracingEnabled(sdk.enableTracing))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn sdk, nil\n}\n\n// WithProvider adds a provider to Reposaur.\nfunc WithProvider(provider provider.Provider) Option {\n\treturn func(sdk *Reposaur) {\n\t\tsdk.providers = append(sdk.providers, provider)\n\t}\n}\n\n// WithLogger sets the logger used by Reposaur.\nfunc WithLogger(logger zerolog.Logger) Option {\n\treturn func(sdk *Reposaur) {\n\t\tsdk.logger = logger\n\t}\n}\n\n// WithTracingEnabled enables or disables policy\n// execution tracing.\nfunc WithTracingEnabled(enabled bool) Option {\n\treturn func(sdk *Reposaur) {\n\t\tsdk.enableTracing = enabled\n\t}\n}\n\n// Logger returns Reposaur logger.\nfunc (sdk Reposaur) Logger() zerolog.Logger {\n\treturn sdk.logger\n}\n\n// Engine returns Reposaur policy engine.\nfunc (sdk Reposaur) Engine() *policy.Engine {\n\treturn sdk.engine\n}\n\n// Check executes the policies loaded against data. Data is checked against every\n// provider to derive a namespace and additional report properties.\nfunc (sdk Reposaur) Check(ctx context.Context, data interface{}) (output.Report, error) {\n\tvar (\n\t\tdataProvider provider.Provider\n\t\tnamespace    provider.Namespace\n\t\terr          error\n\t)\n\n\tfor _, p := range sdk.providers {\n\t\tnamespace, err = provider.DeriveNamespace(p, data)\n\t\tif err != nil {\n\t\t\tif errors.Is(err, provider.ErrNonDerivable) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\treturn output.Report{}, err\n\t\t}\n\n\t\tdataProvider = p\n\t}\n\n\tif dataProvider == nil {\n\t\treturn output.Report{}, errors.New(\"could not derive a valid namespace from data\")\n\t}\n\n\treport, err := sdk.engine.Check(ctx, string(namespace), data)\n\tif err != nil {\n\t\treturn output.Report{}, err\n\t}\n\n\treport.Properties, err = provider.DeriveProperties(dataProvider, namespace, data)\n\tif err != nil && !errors.Is(err, provider.ErrNonDerivable) {\n\t\treturn output.Report{}, err\n\t}\n\n\treturn report, nil\n}\n\nfunc (sdk Reposaur) Test(ctx context.Context) ([]*tester.Result, error) {\n\trunner := tester.NewRunner().\n\t\tEnableTracing(sdk.enableTracing).\n\t\tCapturePrintOutput(true).\n\t\tSetCompiler(sdk.engine.Compiler()).\n\t\tSetModules(sdk.engine.Modules())\n\n\tch, err := runner.RunTests(ctx, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"running tests: %w\", err)\n\t}\n\n\tvar rawResults []*tester.Result\n\tfor result := range ch {\n\t\tif result.Error != nil {\n\t\t\treturn nil, fmt.Errorf(\"run test: %w\", result.Error)\n\t\t}\n\n\t\trawResults = append(rawResults, result)\n\t\tbuf := new(bytes.Buffer)\n\t\ttopdown.PrettyTrace(buf, result.Trace)\n\n\t\tvar traces []string\n\t\tfor _, line := range strings.Split(buf.String(), \"\\n\") {\n\t\t\tif len(line) > 0 {\n\t\t\t\ttraces = append(traces, line)\n\t\t\t}\n\t\t}\n\n\t\tfor _, t := range traces {\n\t\t\tif _, err := fmt.Fprintln(os.Stderr, t); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t}\n\n\treturn rawResults, nil\n}\n\n// Bundle builds a new OCI-compatible policy bundle.\nfunc (sdk Reposaur) Bundle(ctx context.Context, paths []string, out io.Writer) error {\n\tc := compile.New().\n\t\tWithOutput(out).\n\t\tWithTarget(\"rego\").\n\t\tWithPaths(paths...)\n\n\tif err := c.Build(ctx); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "provider/github/client/client.go",
    "content": "package client\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"net/url\"\n\n\t\"github.com/bradleyfalzon/ghinstallation/v2\"\n\t\"github.com/hashicorp/go-retryablehttp\"\n\t\"golang.org/x/oauth2\"\n)\n\nconst (\n\tDefaultBaseURL = \"https://api.github.com\"\n)\n\ntype Client struct {\n\tBaseURL *url.URL\n\n\tclient       *retryablehttp.Client\n\tappTransport *ghinstallation.Transport\n\ttoken        string\n}\n\nfunc NewClient(httpClient *http.Client) *Client {\n\tbaseURL, _ := url.Parse(DefaultBaseURL)\n\tclient := newRetryableClient(httpClient)\n\n\treturn &Client{\n\t\tBaseURL: baseURL,\n\t\tclient:  client,\n\t}\n}\n\nfunc NewTokenClient(ctx context.Context, token string) *Client {\n\ttokenSrc := oauth2.StaticTokenSource(&oauth2.Token{\n\t\tAccessToken: token,\n\t})\n\n\toauthClient := oauth2.NewClient(ctx, tokenSrc)\n\n\tclient := NewClient(oauthClient)\n\tclient.token = token\n\n\treturn client\n}\n\nfunc NewAppClient(_ context.Context, baseURL string, appID, installationID int64, privateKey []byte) (*Client, error) {\n\tappTransport, err := ghinstallation.New(http.DefaultTransport, appID, installationID, privateKey)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tappTransport.BaseURL = baseURL\n\n\thttpClient := &http.Client{\n\t\tTransport: appTransport,\n\t}\n\n\tclient := NewClient(httpClient)\n\tclient.appTransport = appTransport\n\n\treturn client, nil\n}\n\nfunc (c Client) Client() *http.Client {\n\treturn c.client.HTTPClient\n}\n\nfunc (c Client) Token(ctx context.Context) (string, error) {\n\tif c.appTransport != nil {\n\t\treturn c.appTransport.Token(ctx)\n\t}\n\n\treturn c.token, nil\n}\n\nfunc (c Client) NewRequest(method, path string, rawBody any) (*retryablehttp.Request, error) {\n\tu, err := c.BaseURL.Parse(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treq, err := retryablehttp.NewRequest(method, u.String(), rawBody)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif rawBody != nil {\n\t\treq.Header.Set(\"Content-Type\", \"application/json\")\n\t}\n\n\treq.Header.Set(\"User-Agent\", \"reposaur\")\n\n\treturn req, nil\n}\n\nfunc (c Client) Do(req *retryablehttp.Request) (*http.Response, error) {\n\treturn c.client.Do(req)\n}\n\nfunc newRetryableClient(httpClient *http.Client) *retryablehttp.Client {\n\tclient := retryablehttp.NewClient()\n\n\tif httpClient != nil {\n\t\tclient.HTTPClient = httpClient\n\t}\n\n\treturn client\n}\n"
  },
  {
    "path": "provider/github/github.go",
    "content": "package github\n\nimport (\n\t\"github.com/reposaur/reposaur/provider\"\n\t\"github.com/reposaur/reposaur/provider/github/client\"\n\t\"github.com/reposaur/reposaur/provider/github/internal/builtin\"\n)\n\nconst (\n\tIssueNamespace        provider.Namespace = \"github.issue\"\n\tOrganizationNamespace provider.Namespace = \"github.organization\"\n\tPullRequestNamespace  provider.Namespace = \"github.pull_request\"\n\tRepositoryNamespace   provider.Namespace = \"github.repository\"\n\tUserNamespace         provider.Namespace = \"github.user\"\n)\n\ntype GitHub struct {\n\tclient      *client.Client\n\tdataDeriver *DataDeriver\n\tbuiltins    []provider.Builtin\n}\n\nfunc NewProvider(c *client.Client) *GitHub {\n\tif c == nil {\n\t\tc = client.NewClient(nil)\n\t}\n\n\treturn &GitHub{\n\t\tclient: c,\n\t\tbuiltins: []provider.Builtin{\n\t\t\t&builtin.GraphQL{Client: c},\n\t\t\t&builtin.Request{Client: c},\n\t\t},\n\t\tdataDeriver: &DataDeriver{\n\t\t\tnamespaceToKeys: map[provider.Namespace][]string{\n\t\t\t\tIssueNamespace:        {\"reactions\", \"closed_by\"},\n\t\t\t\tOrganizationNamespace: {\"login\", \"members_url\"},\n\t\t\t\tPullRequestNamespace:  {\"base\", \"head\"},\n\t\t\t\tRepositoryNamespace:   {\"owner\", \"full_name\"},\n\t\t\t\tUserNamespace:         {\"login\", \"hireable\"},\n\t\t\t},\n\t\t},\n\t}\n}\n\nfunc (gh GitHub) DeriveNamespace(data map[string]any) (provider.Namespace, error) {\n\treturn gh.dataDeriver.DeriveNamespace(data)\n}\n\nfunc (gh GitHub) DeriveProperties(namespace provider.Namespace, data map[string]any) (map[string]any, error) {\n\treturn gh.dataDeriver.DeriveProperties(namespace, data)\n}\n\nfunc (gh GitHub) Builtins() []provider.Builtin {\n\treturn gh.builtins\n}\n\ntype DataDeriver struct {\n\tnamespaceToKeys map[provider.Namespace][]string\n}\n\nfunc (d DataDeriver) DeriveNamespace(data map[string]any) (provider.Namespace, error) {\n\tfor namespace, keys := range d.namespaceToKeys {\n\t\tvar matches int\n\n\t\tfor _, key := range keys {\n\t\t\tfor dataKey := range data {\n\t\t\t\tif key == dataKey {\n\t\t\t\t\tmatches++\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif matches == len(keys) {\n\t\t\t\treturn namespace, nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn \"\", provider.ErrNonDerivable\n}\n\nfunc (d DataDeriver) DeriveProperties(namespace provider.Namespace, data map[string]any) (map[string]any, error) {\n\tswitch namespace {\n\tcase IssueNamespace, PullRequestNamespace:\n\t\tprops := map[string]any{}\n\n\t\tif id, ok := data[\"id\"]; ok {\n\t\t\tprops[\"id\"] = id\n\t\t}\n\n\t\tif nr, ok := data[\"number\"]; ok {\n\t\t\tprops[\"number\"] = nr\n\t\t}\n\n\t\treturn props, nil\n\n\tcase OrganizationNamespace, UserNamespace:\n\t\tprops := map[string]any{}\n\n\t\tif login, ok := data[\"login\"]; ok {\n\t\t\tprops[\"login\"] = login\n\t\t}\n\n\t\tif name, ok := data[\"name\"]; ok {\n\t\t\tprops[\"name\"] = name\n\t\t}\n\n\t\treturn props, nil\n\n\tcase RepositoryNamespace:\n\t\tprops := map[string]any{}\n\n\t\tif owner, ok := data[\"owner\"].(map[string]any); ok {\n\t\t\tif login, ok := owner[\"login\"]; ok {\n\t\t\t\tprops[\"owner\"] = login\n\t\t\t}\n\t\t}\n\n\t\tif name, ok := data[\"name\"]; ok {\n\t\t\tprops[\"repo\"] = name\n\t\t}\n\n\t\tif defaultBranch, ok := data[\"default_branch\"]; ok {\n\t\t\tprops[\"default_branch\"] = defaultBranch\n\t\t}\n\n\t\treturn props, nil\n\t}\n\n\treturn nil, provider.ErrNonDerivable\n}\n"
  },
  {
    "path": "provider/github/github_test.go",
    "content": "package github_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/reposaur/reposaur/provider\"\n\t\"github.com/reposaur/reposaur/provider/github\"\n)\n\nfunc TestDeriveNamespace(t *testing.T) {\n\tgh := github.NewProvider(nil)\n\n\ttestData := map[provider.Namespace]map[string]any{\n\t\tgithub.IssueNamespace: {\n\t\t\t\"reactions\": \":+1:\",\n\t\t\t\"closed_by\": \"crqra\",\n\t\t},\n\t\tgithub.OrganizationNamespace: {\n\t\t\t\"login\":       \"reposaur\",\n\t\t\t\"members_url\": \"https://reposaur.com\",\n\t\t},\n\t\tgithub.PullRequestNamespace: {\n\t\t\t\"base\": \"main\",\n\t\t\t\"head\": \"feat\",\n\t\t},\n\t\tgithub.RepositoryNamespace: {\n\t\t\t\"owner\":     \"reposaur\",\n\t\t\t\"full_name\": \"reposaur/reposaur\",\n\t\t},\n\t\tgithub.UserNamespace: {\n\t\t\t\"login\":    \"crqra\",\n\t\t\t\"hireable\": true,\n\t\t},\n\t}\n\n\tfor expected, data := range testData {\n\t\tnamespace, err := gh.DeriveNamespace(data)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"testing %s: %s\", expected, err)\n\t\t}\n\n\t\tif namespace != expected {\n\t\t\tt.Fatalf(\"expected namespace to be '%s' got '%s'\", expected, namespace)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "provider/github/internal/builtin/graphql.go",
    "content": "package builtin\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\n\t\"github.com/hashicorp/go-retryablehttp\"\n\t\"github.com/open-policy-agent/opa/ast\"\n\t\"github.com/open-policy-agent/opa/rego\"\n\t\"github.com/open-policy-agent/opa/types\"\n\t\"github.com/reposaur/reposaur/provider/github/client\"\n)\n\ntype GraphQL struct {\n\tClient *client.Client\n}\n\nfunc (gql GraphQL) Func() *rego.Function {\n\treturn &rego.Function{\n\t\tName: \"github.graphql\",\n\t\tDecl: types.NewFunction(\n\t\t\ttypes.Args(\n\t\t\t\ttypes.S,\n\t\t\t\ttypes.NewObject(nil, types.NewDynamicProperty(types.S, types.A)),\n\t\t\t),\n\t\t\ttypes.A,\n\t\t),\n\t\tMemoize: true,\n\t}\n}\n\nfunc (gql GraphQL) Impl(_ rego.BuiltinContext, terms []*ast.Term) (*ast.Term, error) {\n\treq, err := gql.argsToRequest(terms)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tresp, err := gql.Client.Do(req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer resp.Body.Close()\n\n\tvar finalResp response\n\n\tdec := json.NewDecoder(resp.Body)\n\tif err := dec.Decode(&finalResp.Body); err != nil {\n\t\treturn nil, err\n\t}\n\n\tfinalResp.StatusCode = resp.StatusCode\n\n\tif finalResp.StatusCode == http.StatusForbidden {\n\t\tb := finalResp.Body.(map[string]interface{})\n\t\treturn nil, fmt.Errorf(\"forbidden: %s\", b[\"message\"])\n\t}\n\n\tval, err := ast.InterfaceToValue(finalResp)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn ast.NewTerm(val), nil\n}\n\nfunc (gql GraphQL) argsToRequest(terms []*ast.Term) (*retryablehttp.Request, error) {\n\t// FIXME: Function receives 2 arguments but terms includes one additional at last index\n\tif len(terms) != 3 {\n\t\treturn nil, fmt.Errorf(\"wrong number of arguments, expected 2 got %d\", len(terms)-1)\n\t}\n\n\tvar (\n\t\tquery string\n\t\tvars  map[string]any\n\t)\n\n\tif err := ast.As(terms[0].Value, &query); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif err := ast.As(terms[1].Value, &vars); err != nil {\n\t\treturn nil, err\n\t}\n\n\tbody := map[string]any{\n\t\t\"query\":     query,\n\t\t\"variables\": vars,\n\t}\n\n\tbuf := &bytes.Buffer{}\n\tenc := json.NewEncoder(buf)\n\tenc.SetEscapeHTML(false)\n\tif err := enc.Encode(body); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn gql.Client.NewRequest(http.MethodPost, \"/graphql\", buf)\n}\n"
  },
  {
    "path": "provider/github/internal/builtin/request.go",
    "content": "package builtin\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/hashicorp/go-retryablehttp\"\n\t\"github.com/open-policy-agent/opa/ast\"\n\t\"github.com/open-policy-agent/opa/rego\"\n\t\"github.com/open-policy-agent/opa/types\"\n\t\"github.com/reposaur/reposaur/provider/github/client\"\n)\n\ntype Request struct {\n\tClient *client.Client\n}\n\nfunc (r Request) Func() *rego.Function {\n\treturn &rego.Function{\n\t\tName: \"github.request\",\n\t\tDecl: types.NewFunction(\n\t\t\ttypes.Args(\n\t\t\t\ttypes.S,\n\t\t\t\ttypes.NewObject(nil, types.NewDynamicProperty(types.S, types.A)),\n\t\t\t),\n\t\t\ttypes.A,\n\t\t),\n\t\tMemoize: true,\n\t}\n}\n\nfunc (r Request) Impl(_ rego.BuiltinContext, terms []*ast.Term) (*ast.Term, error) {\n\treq, err := r.argsToRequest(terms)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tresp, err := r.Client.Do(req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer resp.Body.Close()\n\n\tvar finalResp response\n\n\tdec := json.NewDecoder(resp.Body)\n\tif err := dec.Decode(&finalResp.Body); err != nil {\n\t\treturn nil, err\n\t}\n\n\tfinalResp.StatusCode = resp.StatusCode\n\n\tif finalResp.StatusCode == http.StatusForbidden {\n\t\tb := finalResp.Body.(map[string]interface{})\n\t\treturn nil, fmt.Errorf(\"forbidden: %s\", b[\"message\"])\n\t}\n\n\tval, err := ast.InterfaceToValue(finalResp)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn ast.NewTerm(val), nil\n}\n\nfunc (r Request) argsToRequest(terms []*ast.Term) (*retryablehttp.Request, error) {\n\t// FIXME: Function receives 2 arguments but terms includes one additional at last index\n\tif len(terms) != 3 {\n\t\treturn nil, fmt.Errorf(\"wrong number of arguments, expected 2 got %d\", len(terms)-1)\n\t}\n\n\tvar (\n\t\tpath string\n\t\tdata map[string]any\n\t)\n\n\tif err := ast.As(terms[0].Value, &path); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif err := ast.As(terms[1].Value, &data); err != nil {\n\t\treturn nil, err\n\t}\n\n\tmethod, path, err := r.parsePath(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif method != http.MethodGet {\n\t\treturn nil, fmt.Errorf(\"only GET requests are supported, got '%s'\", method)\n\t}\n\n\tpathParams := r.parsePathParams(path)\n\n\tfor _, p := range pathParams {\n\t\tv, err := r.valueToString(data[p])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tpath = strings.Replace(path, \"{\"+p+\"}\", v, 1)\n\t\tdelete(data, p)\n\t}\n\n\tqs := url.Values{}\n\n\tfor k, v := range data {\n\t\tv, err := r.valueToString(v)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tqs.Add(k, v)\n\t\tdelete(data, k)\n\t}\n\n\tu, err := url.Parse(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tu.RawQuery = qs.Encode()\n\n\treturn r.Client.NewRequest(method, u.String(), nil)\n}\n\nfunc (r Request) parsePath(p string) (string, string, error) {\n\tpathParts := strings.Split(p, \" \")\n\n\tif len(pathParts) != 2 {\n\t\treturn \"\", \"\", fmt.Errorf(\"wrong number of parts in path, expected 2 got %d\", len(pathParts))\n\t}\n\n\tvar (\n\t\tmethod = strings.ToUpper(pathParts[0])\n\t\tpath   = pathParts[1]\n\t)\n\n\treturn method, path, nil\n}\n\nfunc (r Request) parsePathParams(path string) []string {\n\tregex := regexp.MustCompile(`{[a-z]+}`)\n\tmatches := regex.FindAllString(path, -1)\n\n\tvar params []string\n\tfor _, v := range matches {\n\t\tp := strings.Replace(v, \"{\", \"\", 1)\n\t\tp = strings.Replace(p, \"}\", \"\", 1)\n\t\tparams = append(params, p)\n\t}\n\n\treturn params\n}\n\nfunc (r Request) valueToString(v interface{}) (string, error) {\n\tswitch tv := v.(type) {\n\tcase string:\n\t\treturn tv, nil\n\n\tcase json.Number:\n\t\treturn tv.String(), nil\n\n\tcase int64:\n\t\treturn strconv.Itoa(int(tv)), nil\n\t}\n\n\treturn \"\", fmt.Errorf(\"parse error: can't parse '%v' to string\", v)\n}\n"
  },
  {
    "path": "provider/github/internal/builtin/response.go",
    "content": "package builtin\n\ntype response struct {\n\tStatusCode int         `json:\"status\"`\n\tBody       interface{} `json:\"body\"`\n}\n"
  },
  {
    "path": "provider/provider.go",
    "content": "package provider\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"reflect\"\n\n\t\"github.com/open-policy-agent/opa/ast\"\n\t\"github.com/open-policy-agent/opa/rego\"\n)\n\nvar ErrNonDerivable = errors.New(\"data is non derivable\")\n\ntype Namespace string\n\n// DataDeriver is the interface that provides functions to derive a policy\n// namespace and report properties from input data for a specific provider.\ntype DataDeriver interface {\n\tDeriveNamespace(map[string]any) (Namespace, error)\n\tDeriveProperties(Namespace, map[string]any) (map[string]any, error)\n}\n\n// Provider is the interface that provides the functions required to work with\n// a specific provider, namely a function to register built-in functions in\n// the policy engine and functions to derive required information from input data.\n// See DataDeriver.\ntype Provider interface {\n\tDataDeriver\n\n\tBuiltins() []Builtin\n}\n\n// Builtin is represents a built-in function in the policy engine. It specifies\n// the function signature and the function implementation.\ntype Builtin interface {\n\tFunc() *rego.Function\n\tImpl(rego.BuiltinContext, []*ast.Term) (*ast.Term, error)\n}\n\nfunc DeriveNamespace(deriver DataDeriver, data any) (Namespace, error) {\n\tm, err := dataToMap(data)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn deriver.DeriveNamespace(m)\n}\n\nfunc DeriveProperties(deriver DataDeriver, namespace Namespace, data any) (map[string]any, error) {\n\tm, err := dataToMap(data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn deriver.DeriveProperties(namespace, m)\n}\n\nfunc dataToMap(data any) (map[string]any, error) {\n\tval := reflect.ValueOf(data)\n\n\t// We can never derive anything from a slice, only from maps or structures\n\tif val.Kind() == reflect.Slice {\n\t\treturn nil, ErrNonDerivable\n\t}\n\n\t// If data is already a map we just convert it to map[string]any\n\tif val.Kind() == reflect.Map {\n\t\tm := make(map[string]any, val.Len())\n\t\tfor _, k := range val.MapKeys() {\n\t\t\tif k.Kind() == reflect.String {\n\t\t\t\tm[k.String()] = val.MapIndex(k).Interface()\n\t\t\t}\n\t\t}\n\t\treturn m, nil\n\t}\n\n\tif val.Kind() != reflect.Struct {\n\t\treturn nil, ErrNonDerivable\n\t}\n\n\t// Here we have a structure, we rely on json package to convert it into\n\t// a map for us.\n\trawData, err := json.Marshal(data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar m map[string]any\n\n\tif err := json.Unmarshal(rawData, &m); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn m, nil\n}\n"
  },
  {
    "path": "provider/provider_test.go",
    "content": "package provider\n\nimport (\n\t\"errors\"\n\t\"testing\"\n)\n\nfunc TestMapDataToMap(t *testing.T) {\n\tdataMap := map[string]any{\n\t\t\"foo\": \"bar\",\n\t\t\"bar\": 10,\n\t}\n\n\tm, err := dataToMap(dataMap)\n\tif err != nil {\n\t\tt.Error(err)\n\t}\n\n\tif foo, ok := m[\"foo\"]; !ok || foo != \"bar\" {\n\t\tt.Fail()\n\t}\n\n\tif bar, ok := m[\"bar\"]; !ok || bar != 10 {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestStructDataToMap(t *testing.T) {\n\tdataStruct := struct {\n\t\tFoo string `json:\"foo\"`\n\t\tBar int    `json:\"bar\"`\n\t}{\n\t\tFoo: \"bar\",\n\t\tBar: 10,\n\t}\n\n\tm, err := dataToMap(dataStruct)\n\tif err != nil {\n\t\tt.Error(err)\n\t}\n\n\tif foo, ok := m[\"foo\"]; !ok || foo != \"bar\" {\n\t\tt.Fail()\n\t}\n\n\t// JSON numbers are stored as float64 when converting to interface{}\n\t// See https://pkg.go.dev/encoding/json#Unmarshal\n\tif bar, ok := m[\"bar\"]; !ok || bar != 10.0 {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestAnyDataToMap(t *testing.T) {\n\t_, err := dataToMap(10)\n\tif !errors.Is(err, ErrNonDerivable) {\n\t\tt.Errorf(\"expected error '%s' got '%s'\", ErrNonDerivable, err)\n\t}\n\n\t_, err = dataToMap(\"foo\")\n\tif !errors.Is(err, ErrNonDerivable) {\n\t\tt.Errorf(\"expected error '%s' got '%s'\", ErrNonDerivable, err)\n\t}\n\n\t_, err = dataToMap([]string{\"foo\", \"bar\"})\n\tif !errors.Is(err, ErrNonDerivable) {\n\t\tt.Errorf(\"expected error '%s' got '%s'\", ErrNonDerivable, err)\n\t}\n}\n"
  },
  {
    "path": "scripts/completions.sh",
    "content": "#!/bin/sh\nset -e\nrm -rf completions\nmkdir completions\nfor sh in bash zsh fish; do\n\tgo run cmd/rsr/rsr.go completion \"$sh\" > \"completions/rsr.$sh\"\ndone"
  }
]