Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audit log GraphQL API #5530

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open

Audit log GraphQL API #5530

wants to merge 17 commits into from

Conversation

TuvalSimha
Copy link
Collaborator

@TuvalSimha TuvalSimha commented Aug 26, 2024

Background

This pull request introduces new modules titled Audit Log. The audit logs comprehensively document all user activities and system events, organized by each organization.

Description

  • A new GraphQL schema has been established, along with the creation of an interface named AuditLog.
  • Audit log cases have been implemented by developing a new type that adheres to the AuditLog interface.
  • A new provider, named AuditLogManager, has been created with Clickhouse to facilitate database updates. This provider offers three primary functions:
  1. createLogAuditEvent: Utilized for inserting new log/event data.
  2. getPaginatedAuditLogs: Employed for retrieving all data from the database.
  3. getAuditLogsCount: Used to count the total number of records in the database.
  • The provider oversees the event/record type through a new type called AuditLogEvent, with each case accompanied by a zod schema to enhance type safety.
  • Currently, I have included a single example of a case that records user activity - you can see it here, and I welcome feedback on the next steps.

@kamilkisiela @dotansimha @n1ru4l
I would appreciate your thoughts on this and any suggestions for modifications

Copy link

changeset-bot bot commented Aug 26, 2024

⚠️ No Changeset found

Latest commit: 2c42586

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

github-actions bot commented Aug 26, 2024

🐋 This PR was built and pushed to the following Docker images (tag: 51e1bff0cf454929938d132c53e5a58d9b1f70df):

Docker Bake metadata
{
"app": {
  "buildx.build.ref": "builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e/builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e0/m342hmq75is4nyjl55o5qmq0g",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
    "digest": "sha256:3e445164324676a3ce0d9d661c941725245f590168fc55ceb77248ac3b78ee25",
    "size": 685
  },
  "containerimage.digest": "sha256:3e445164324676a3ce0d9d661c941725245f590168fc55ceb77248ac3b78ee25",
  "image.name": "ghcr.io/graphql-hive/app:51e1bff0cf454929938d132c53e5a58d9b1f70df,ghcr.io/graphql-hive/app:tuval_audit_log_api"
},
"buildx.build.warnings": [
  {
    "vertex": "sha256:6e05ca598f79881bac4957dcedf8679ea4470de8bc5d7241c3507cbec4dcbea6",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDExKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjguMC1zbGltCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IGNhLWNlcnRpZmljYXRlcwoKV09SS0RJUiAvdXNyL3NyYy9hcHAKCkNPUFkgLS1mcm9tPWRpc3QgLiAvdXNyL3NyYy9hcHAvCkNPUFkgLS1mcm9tPXNoYXJlZCAuIC8KCkVOViBFTlZJUk9OTUVOVCBwcm9kdWN0aW9uCkVOViBOT0RFX0VOViBwcm9kdWN0aW9uCkVOViBSRUxFQVNFICRSRUxFQVNFCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 11
        },
        "end": {
          "line": 11
        }
      }
    ]
  },
  {
    "vertex": "sha256:6e05ca598f79881bac4957dcedf8679ea4470de8bc5d7241c3507cbec4dcbea6",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDEyKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjguMC1zbGltCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IGNhLWNlcnRpZmljYXRlcwoKV09SS0RJUiAvdXNyL3NyYy9hcHAKCkNPUFkgLS1mcm9tPWRpc3QgLiAvdXNyL3NyYy9hcHAvCkNPUFkgLS1mcm9tPXNoYXJlZCAuIC8KCkVOViBFTlZJUk9OTUVOVCBwcm9kdWN0aW9uCkVOViBOT0RFX0VOViBwcm9kdWN0aW9uCkVOViBSRUxFQVNFICRSRUxFQVNFCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 12
        },
        "end": {
          "line": 12
        }
      }
    ]
  },
  {
    "vertex": "sha256:7cccc5bd1bab6d2f57cdad3bdb1361b7b889bf33700a9fe7bd245ab7593a2baf",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRQT1JUJyAobGluZSAyMik=",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjguMC1zbGltCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IHdnZXQgY2EtY2VydGlmaWNhdGVzICYmIHJtIC1yZiAvdmFyL2xpYi9hcHQvbGlzdHMvKgoKQVJHIFNFUlZJQ0VfRElSX05BTUUKV09SS0RJUiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUKCkNPUFkgLS1mcm9tPWRpc3QgLiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUvCkNPUFkgLS1mcm9tPXNoYXJlZCAuIC8KCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5saWNlbnNlcz1NSVQKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnRpdGxlPSRJTUFHRV9USVRMRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVyc2lvbj0kUkVMRUFTRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuZGVzY3JpcHRpb249JElNQUdFX0RFU0NSSVBUSU9OCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5hdXRob3JzPSJUaGUgR3VpbGQiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZW5kb3I9IkthbWlsIEtpc2llbGEiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS51cmw9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5zb3VyY2U9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQpFTlYgUE9SVCAkUE9SVAoKSEVBTFRIQ0hFQ0sgLS1pbnRlcnZhbD01cyBcCiAgLS10aW1lb3V0PTVzIFwKICAtLXN0YXJ0LXBlcmlvZD01cyBcCiAgLS1yZXRyaWVzPTYgXAogIENNRCAkSEVBTFRIQ0hFQ0tfQ01ECgpFTlRSWVBPSU5UIFsgIi9lbnRyeXBvaW50LnNoIiBdCg==",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 22
        },
        "end": {
          "line": 22
        }
      }
    ]
  },
  {
    "vertex": "sha256:6e05ca598f79881bac4957dcedf8679ea4470de8bc5d7241c3507cbec4dcbea6",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDEwKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjguMC1zbGltCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IGNhLWNlcnRpZmljYXRlcwoKV09SS0RJUiAvdXNyL3NyYy9hcHAKCkNPUFkgLS1mcm9tPWRpc3QgLiAvdXNyL3NyYy9hcHAvCkNPUFkgLS1mcm9tPXNoYXJlZCAuIC8KCkVOViBFTlZJUk9OTUVOVCBwcm9kdWN0aW9uCkVOViBOT0RFX0VOViBwcm9kdWN0aW9uCkVOViBSRUxFQVNFICRSRUxFQVNFCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 10
        },
        "end": {
          "line": 10
        }
      }
    ]
  },
  {
    "vertex": "sha256:7cccc5bd1bab6d2f57cdad3bdb1361b7b889bf33700a9fe7bd245ab7593a2baf",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDIwKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjguMC1zbGltCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IHdnZXQgY2EtY2VydGlmaWNhdGVzICYmIHJtIC1yZiAvdmFyL2xpYi9hcHQvbGlzdHMvKgoKQVJHIFNFUlZJQ0VfRElSX05BTUUKV09SS0RJUiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUKCkNPUFkgLS1mcm9tPWRpc3QgLiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUvCkNPUFkgLS1mcm9tPXNoYXJlZCAuIC8KCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5saWNlbnNlcz1NSVQKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnRpdGxlPSRJTUFHRV9USVRMRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVyc2lvbj0kUkVMRUFTRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuZGVzY3JpcHRpb249JElNQUdFX0RFU0NSSVBUSU9OCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5hdXRob3JzPSJUaGUgR3VpbGQiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZW5kb3I9IkthbWlsIEtpc2llbGEiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS51cmw9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5zb3VyY2U9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQpFTlYgUE9SVCAkUE9SVAoKSEVBTFRIQ0hFQ0sgLS1pbnRlcnZhbD01cyBcCiAgLS10aW1lb3V0PTVzIFwKICAtLXN0YXJ0LXBlcmlvZD01cyBcCiAgLS1yZXRyaWVzPTYgXAogIENNRCAkSEVBTFRIQ0hFQ0tfQ01ECgpFTlRSWVBPSU5UIFsgIi9lbnRyeXBvaW50LnNoIiBdCg==",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 20
        },
        "end": {
          "line": 20
        }
      }
    ]
  },
  {
    "vertex": "sha256:7cccc5bd1bab6d2f57cdad3bdb1361b7b889bf33700a9fe7bd245ab7593a2baf",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRSRUxFQVNFJyAobGluZSAyMSk=",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjguMC1zbGltCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IHdnZXQgY2EtY2VydGlmaWNhdGVzICYmIHJtIC1yZiAvdmFyL2xpYi9hcHQvbGlzdHMvKgoKQVJHIFNFUlZJQ0VfRElSX05BTUUKV09SS0RJUiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUKCkNPUFkgLS1mcm9tPWRpc3QgLiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUvCkNPUFkgLS1mcm9tPXNoYXJlZCAuIC8KCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5saWNlbnNlcz1NSVQKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnRpdGxlPSRJTUFHRV9USVRMRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVyc2lvbj0kUkVMRUFTRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuZGVzY3JpcHRpb249JElNQUdFX0RFU0NSSVBUSU9OCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5hdXRob3JzPSJUaGUgR3VpbGQiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZW5kb3I9IkthbWlsIEtpc2llbGEiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS51cmw9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5zb3VyY2U9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQpFTlYgUE9SVCAkUE9SVAoKSEVBTFRIQ0hFQ0sgLS1pbnRlcnZhbD01cyBcCiAgLS10aW1lb3V0PTVzIFwKICAtLXN0YXJ0LXBlcmlvZD01cyBcCiAgLS1yZXRyaWVzPTYgXAogIENNRCAkSEVBTFRIQ0hFQ0tfQ01ECgpFTlRSWVBPSU5UIFsgIi9lbnRyeXBvaW50LnNoIiBdCg==",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 21
        },
        "end": {
          "line": 21
        }
      }
    ]
  },
  {
    "vertex": "sha256:6e05ca598f79881bac4957dcedf8679ea4470de8bc5d7241c3507cbec4dcbea6",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRSRUxFQVNFJyAobGluZSAxMik=",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjguMC1zbGltCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IGNhLWNlcnRpZmljYXRlcwoKV09SS0RJUiAvdXNyL3NyYy9hcHAKCkNPUFkgLS1mcm9tPWRpc3QgLiAvdXNyL3NyYy9hcHAvCkNPUFkgLS1mcm9tPXNoYXJlZCAuIC8KCkVOViBFTlZJUk9OTUVOVCBwcm9kdWN0aW9uCkVOViBOT0RFX0VOViBwcm9kdWN0aW9uCkVOViBSRUxFQVNFICRSRUxFQVNFCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 12
        },
        "end": {
          "line": 12
        }
      }
    ]
  },
  {
    "vertex": "sha256:6e05ca598f79881bac4957dcedf8679ea4470de8bc5d7241c3507cbec4dcbea6",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9USVRMRScgKGxpbmUgMTUp",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjguMC1zbGltCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IGNhLWNlcnRpZmljYXRlcwoKV09SS0RJUiAvdXNyL3NyYy9hcHAKCkNPUFkgLS1mcm9tPWRpc3QgLiAvdXNyL3NyYy9hcHAvCkNPUFkgLS1mcm9tPXNoYXJlZCAuIC8KCkVOViBFTlZJUk9OTUVOVCBwcm9kdWN0aW9uCkVOViBOT0RFX0VOViBwcm9kdWN0aW9uCkVOViBSRUxFQVNFICRSRUxFQVNFCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 15
        },
        "end": {
          "line": 15
        }
      }
    ]
  },
  {
    "vertex": "sha256:6e05ca598f79881bac4957dcedf8679ea4470de8bc5d7241c3507cbec4dcbea6",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9ERVNDUklQVElPTicgKGxpbmUgMTcp",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjguMC1zbGltCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IGNhLWNlcnRpZmljYXRlcwoKV09SS0RJUiAvdXNyL3NyYy9hcHAKCkNPUFkgLS1mcm9tPWRpc3QgLiAvdXNyL3NyYy9hcHAvCkNPUFkgLS1mcm9tPXNoYXJlZCAuIC8KCkVOViBFTlZJUk9OTUVOVCBwcm9kdWN0aW9uCkVOViBOT0RFX0VOViBwcm9kdWN0aW9uCkVOViBSRUxFQVNFICRSRUxFQVNFCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 17
        },
        "end": {
          "line": 17
        }
      }
    ]
  },
  {
    "vertex": "sha256:7cccc5bd1bab6d2f57cdad3bdb1361b7b889bf33700a9fe7bd245ab7593a2baf",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9USVRMRScgKGxpbmUgMTIp",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjguMC1zbGltCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IHdnZXQgY2EtY2VydGlmaWNhdGVzICYmIHJtIC1yZiAvdmFyL2xpYi9hcHQvbGlzdHMvKgoKQVJHIFNFUlZJQ0VfRElSX05BTUUKV09SS0RJUiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUKCkNPUFkgLS1mcm9tPWRpc3QgLiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUvCkNPUFkgLS1mcm9tPXNoYXJlZCAuIC8KCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5saWNlbnNlcz1NSVQKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnRpdGxlPSRJTUFHRV9USVRMRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVyc2lvbj0kUkVMRUFTRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuZGVzY3JpcHRpb249JElNQUdFX0RFU0NSSVBUSU9OCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5hdXRob3JzPSJUaGUgR3VpbGQiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZW5kb3I9IkthbWlsIEtpc2llbGEiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS51cmw9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5zb3VyY2U9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQpFTlYgUE9SVCAkUE9SVAoKSEVBTFRIQ0hFQ0sgLS1pbnRlcnZhbD01cyBcCiAgLS10aW1lb3V0PTVzIFwKICAtLXN0YXJ0LXBlcmlvZD01cyBcCiAgLS1yZXRyaWVzPTYgXAogIENNRCAkSEVBTFRIQ0hFQ0tfQ01ECgpFTlRSWVBPSU5UIFsgIi9lbnRyeXBvaW50LnNoIiBdCg==",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 12
        },
        "end": {
          "line": 12
        }
      }
    ]
  },
  {
    "vertex": "sha256:7cccc5bd1bab6d2f57cdad3bdb1361b7b889bf33700a9fe7bd245ab7593a2baf",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRSRUxFQVNFJyAobGluZSAxMyk=",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjguMC1zbGltCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IHdnZXQgY2EtY2VydGlmaWNhdGVzICYmIHJtIC1yZiAvdmFyL2xpYi9hcHQvbGlzdHMvKgoKQVJHIFNFUlZJQ0VfRElSX05BTUUKV09SS0RJUiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUKCkNPUFkgLS1mcm9tPWRpc3QgLiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUvCkNPUFkgLS1mcm9tPXNoYXJlZCAuIC8KCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5saWNlbnNlcz1NSVQKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnRpdGxlPSRJTUFHRV9USVRMRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVyc2lvbj0kUkVMRUFTRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuZGVzY3JpcHRpb249JElNQUdFX0RFU0NSSVBUSU9OCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5hdXRob3JzPSJUaGUgR3VpbGQiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZW5kb3I9IkthbWlsIEtpc2llbGEiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS51cmw9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5zb3VyY2U9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQpFTlYgUE9SVCAkUE9SVAoKSEVBTFRIQ0hFQ0sgLS1pbnRlcnZhbD01cyBcCiAgLS10aW1lb3V0PTVzIFwKICAtLXN0YXJ0LXBlcmlvZD01cyBcCiAgLS1yZXRyaWVzPTYgXAogIENNRCAkSEVBTFRIQ0hFQ0tfQ01ECgpFTlRSWVBPSU5UIFsgIi9lbnRyeXBvaW50LnNoIiBdCg==",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 13
        },
        "end": {
          "line": 13
        }
      }
    ]
  },
  {
    "vertex": "sha256:7cccc5bd1bab6d2f57cdad3bdb1361b7b889bf33700a9fe7bd245ab7593a2baf",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9ERVNDUklQVElPTicgKGxpbmUgMTQp",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjguMC1zbGltCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IHdnZXQgY2EtY2VydGlmaWNhdGVzICYmIHJtIC1yZiAvdmFyL2xpYi9hcHQvbGlzdHMvKgoKQVJHIFNFUlZJQ0VfRElSX05BTUUKV09SS0RJUiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUKCkNPUFkgLS1mcm9tPWRpc3QgLiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUvCkNPUFkgLS1mcm9tPXNoYXJlZCAuIC8KCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5saWNlbnNlcz1NSVQKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnRpdGxlPSRJTUFHRV9USVRMRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVyc2lvbj0kUkVMRUFTRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuZGVzY3JpcHRpb249JElNQUdFX0RFU0NSSVBUSU9OCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5hdXRob3JzPSJUaGUgR3VpbGQiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZW5kb3I9IkthbWlsIEtpc2llbGEiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS51cmw9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5zb3VyY2U9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQpFTlYgUE9SVCAkUE9SVAoKSEVBTFRIQ0hFQ0sgLS1pbnRlcnZhbD01cyBcCiAgLS10aW1lb3V0PTVzIFwKICAtLXN0YXJ0LXBlcmlvZD01cyBcCiAgLS1yZXRyaWVzPTYgXAogIENNRCAkSEVBTFRIQ0hFQ0tfQ01ECgpFTlRSWVBPSU5UIFsgIi9lbnRyeXBvaW50LnNoIiBdCg==",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 14
        },
        "end": {
          "line": 14
        }
      }
    ]
  },
  {
    "vertex": "sha256:7cccc5bd1bab6d2f57cdad3bdb1361b7b889bf33700a9fe7bd245ab7593a2baf",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDIxKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjguMC1zbGltCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IHdnZXQgY2EtY2VydGlmaWNhdGVzICYmIHJtIC1yZiAvdmFyL2xpYi9hcHQvbGlzdHMvKgoKQVJHIFNFUlZJQ0VfRElSX05BTUUKV09SS0RJUiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUKCkNPUFkgLS1mcm9tPWRpc3QgLiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUvCkNPUFkgLS1mcm9tPXNoYXJlZCAuIC8KCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5saWNlbnNlcz1NSVQKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnRpdGxlPSRJTUFHRV9USVRMRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVyc2lvbj0kUkVMRUFTRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuZGVzY3JpcHRpb249JElNQUdFX0RFU0NSSVBUSU9OCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5hdXRob3JzPSJUaGUgR3VpbGQiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZW5kb3I9IkthbWlsIEtpc2llbGEiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS51cmw9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5zb3VyY2U9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQpFTlYgUE9SVCAkUE9SVAoKSEVBTFRIQ0hFQ0sgLS1pbnRlcnZhbD01cyBcCiAgLS10aW1lb3V0PTVzIFwKICAtLXN0YXJ0LXBlcmlvZD01cyBcCiAgLS1yZXRyaWVzPTYgXAogIENNRCAkSEVBTFRIQ0hFQ0tfQ01ECgpFTlRSWVBPSU5UIFsgIi9lbnRyeXBvaW50LnNoIiBdCg==",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 21
        },
        "end": {
          "line": 21
        }
      }
    ]
  },
  {
    "vertex": "sha256:7cccc5bd1bab6d2f57cdad3bdb1361b7b889bf33700a9fe7bd245ab7593a2baf",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDIyKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjguMC1zbGltCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IHdnZXQgY2EtY2VydGlmaWNhdGVzICYmIHJtIC1yZiAvdmFyL2xpYi9hcHQvbGlzdHMvKgoKQVJHIFNFUlZJQ0VfRElSX05BTUUKV09SS0RJUiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUKCkNPUFkgLS1mcm9tPWRpc3QgLiAvdXNyL3NyYy9hcHAvJFNFUlZJQ0VfRElSX05BTUUvCkNPUFkgLS1mcm9tPXNoYXJlZCAuIC8KCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5saWNlbnNlcz1NSVQKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnRpdGxlPSRJTUFHRV9USVRMRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVyc2lvbj0kUkVMRUFTRQpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuZGVzY3JpcHRpb249JElNQUdFX0RFU0NSSVBUSU9OCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5hdXRob3JzPSJUaGUgR3VpbGQiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZW5kb3I9IkthbWlsIEtpc2llbGEiCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS51cmw9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5zb3VyY2U9Imh0dHBzOi8vZ2l0aHViLmNvbS9ncmFwaHFsLWhpdmUvcGxhdGZvcm0iCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQpFTlYgUE9SVCAkUE9SVAoKSEVBTFRIQ0hFQ0sgLS1pbnRlcnZhbD01cyBcCiAgLS10aW1lb3V0PTVzIFwKICAtLXN0YXJ0LXBlcmlvZD01cyBcCiAgLS1yZXRyaWVzPTYgXAogIENNRCAkSEVBTFRIQ0hFQ0tfQ01ECgpFTlRSWVBPSU5UIFsgIi9lbnRyeXBvaW50LnNoIiBdCg==",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 22
        },
        "end": {
          "line": 22
        }
      }
    ]
  }
],
"composition-federation-2": {
  "buildx.build.ref": "builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e/builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e0/a31x3vmsv1l52sw2g4vtg7gkn",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
    "digest": "sha256:4a79c316db10501cc96275f9d18b6b1d41a71c3f80f532cadc88dfa38e3bf5b2",
    "size": 685
  },
  "containerimage.digest": "sha256:4a79c316db10501cc96275f9d18b6b1d41a71c3f80f532cadc88dfa38e3bf5b2",
  "image.name": "ghcr.io/graphql-hive/composition-federation-2:51e1bff0cf454929938d132c53e5a58d9b1f70df,ghcr.io/graphql-hive/composition-federation-2:tuval_audit_log_api"
},
"emails": {
  "buildx.build.ref": "builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e/builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e0/wkwiow892dls9sbywd03zc71o",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
    "digest": "sha256:1ca640c9255ed061aec33704f9cb7c284ff352c117d06a9f76d4a02b9cd9eed4",
    "size": 685
  },
  "containerimage.digest": "sha256:1ca640c9255ed061aec33704f9cb7c284ff352c117d06a9f76d4a02b9cd9eed4",
  "image.name": "ghcr.io/graphql-hive/emails:51e1bff0cf454929938d132c53e5a58d9b1f70df,ghcr.io/graphql-hive/emails:tuval_audit_log_api"
},
"policy": {
  "buildx.build.ref": "builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e/builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e0/hyz4sttgjfjv6gabvvptbak6z",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
    "digest": "sha256:2e36d28c0bbbf842a6feb0bdd107e6ebb0b89e17215842f29f30defba4f7bdcd",
    "size": 685
  },
  "containerimage.digest": "sha256:2e36d28c0bbbf842a6feb0bdd107e6ebb0b89e17215842f29f30defba4f7bdcd",
  "image.name": "ghcr.io/graphql-hive/policy:51e1bff0cf454929938d132c53e5a58d9b1f70df,ghcr.io/graphql-hive/policy:tuval_audit_log_api"
},
"rate-limit": {
  "buildx.build.ref": "builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e/builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e0/i9o70t3bbu6mne4vfcrogi22e",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
    "digest": "sha256:cb607637369ff9dbf0dbe68a18bbb46bd8f64af4ed883acd2c1e74fd14426c8e",
    "size": 685
  },
  "containerimage.digest": "sha256:cb607637369ff9dbf0dbe68a18bbb46bd8f64af4ed883acd2c1e74fd14426c8e",
  "image.name": "ghcr.io/graphql-hive/rate-limit:51e1bff0cf454929938d132c53e5a58d9b1f70df,ghcr.io/graphql-hive/rate-limit:tuval_audit_log_api"
},
"schema": {
  "buildx.build.ref": "builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e/builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e0/nx4a252tyygaotbn8usemhf5j",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
    "digest": "sha256:a7347d77b0ebb8cab6e198359045c6c8bc89330a0df23a5c2760aa52d0dc1208",
    "size": 685
  },
  "containerimage.digest": "sha256:a7347d77b0ebb8cab6e198359045c6c8bc89330a0df23a5c2760aa52d0dc1208",
  "image.name": "ghcr.io/graphql-hive/schema:51e1bff0cf454929938d132c53e5a58d9b1f70df,ghcr.io/graphql-hive/schema:tuval_audit_log_api"
},
"server": {
  "buildx.build.ref": "builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e/builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e0/z536u4tf3rnj1o2rkl924974c",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
    "digest": "sha256:d934eae4d95771f02fd584890561bf19753bbe2fb0c8fda57b69f0ef214ce539",
    "size": 685
  },
  "containerimage.digest": "sha256:d934eae4d95771f02fd584890561bf19753bbe2fb0c8fda57b69f0ef214ce539",
  "image.name": "ghcr.io/graphql-hive/server:51e1bff0cf454929938d132c53e5a58d9b1f70df,ghcr.io/graphql-hive/server:tuval_audit_log_api"
},
"storage": {
  "buildx.build.ref": "builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e/builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e0/ojckc5r7yuorw9kwbzmio6595",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
    "digest": "sha256:b690b14da928da0ab9dc8fd6c819a340c2d45d139f19478da7384168092db4c8",
    "size": 685
  },
  "containerimage.digest": "sha256:b690b14da928da0ab9dc8fd6c819a340c2d45d139f19478da7384168092db4c8",
  "image.name": "ghcr.io/graphql-hive/storage:51e1bff0cf454929938d132c53e5a58d9b1f70df,ghcr.io/graphql-hive/storage:tuval_audit_log_api"
},
"stripe-billing": {
  "buildx.build.ref": "builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e/builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e0/ifd5wx52li7k23nqzqjpnoy8f",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
    "digest": "sha256:ac417f16506e65f91934039f791b9b3c928090ccd8295d826cbb7c943f1560dc",
    "size": 685
  },
  "containerimage.digest": "sha256:ac417f16506e65f91934039f791b9b3c928090ccd8295d826cbb7c943f1560dc",
  "image.name": "ghcr.io/graphql-hive/stripe-billing:51e1bff0cf454929938d132c53e5a58d9b1f70df,ghcr.io/graphql-hive/stripe-billing:tuval_audit_log_api"
},
"tokens": {
  "buildx.build.ref": "builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e/builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e0/jhd4ohkfslxd96jqfq2wwkhwr",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
    "digest": "sha256:cf0cdc707715530c2e4cf64c51f4cd34df8411a7b6114951b4fa05fa9014bc93",
    "size": 685
  },
  "containerimage.digest": "sha256:cf0cdc707715530c2e4cf64c51f4cd34df8411a7b6114951b4fa05fa9014bc93",
  "image.name": "ghcr.io/graphql-hive/tokens:51e1bff0cf454929938d132c53e5a58d9b1f70df,ghcr.io/graphql-hive/tokens:tuval_audit_log_api"
},
"usage": {
  "buildx.build.ref": "builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e/builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e0/mpg0h8bo3nh2rmb8w4vghj4bv",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
    "digest": "sha256:f9521f495619c2e25cf9a5871c46530c9dea320520a23ea423980bfa8248b385",
    "size": 685
  },
  "containerimage.digest": "sha256:f9521f495619c2e25cf9a5871c46530c9dea320520a23ea423980bfa8248b385",
  "image.name": "ghcr.io/graphql-hive/usage:51e1bff0cf454929938d132c53e5a58d9b1f70df,ghcr.io/graphql-hive/usage:tuval_audit_log_api"
},
"usage-estimator": {
  "buildx.build.ref": "builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e/builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e0/rga6o5yy6mnigtglx50wfdxi7",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
    "digest": "sha256:6913120be74f8ed84b3ef61aea57febb2172a51ecf23c6b3b09c31bb1c4a3d71",
    "size": 685
  },
  "containerimage.digest": "sha256:6913120be74f8ed84b3ef61aea57febb2172a51ecf23c6b3b09c31bb1c4a3d71",
  "image.name": "ghcr.io/graphql-hive/usage-estimator:51e1bff0cf454929938d132c53e5a58d9b1f70df,ghcr.io/graphql-hive/usage-estimator:tuval_audit_log_api"
},
"usage-ingestor": {
  "buildx.build.ref": "builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e/builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e0/z5nk9j4oimy5fe2uliaqruxkw",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
    "digest": "sha256:463d9a92a00e2c659a9d92d52c83ca1949b20f864f505522a2d6c52d3dae4ed1",
    "size": 685
  },
  "containerimage.digest": "sha256:463d9a92a00e2c659a9d92d52c83ca1949b20f864f505522a2d6c52d3dae4ed1",
  "image.name": "ghcr.io/graphql-hive/usage-ingestor:51e1bff0cf454929938d132c53e5a58d9b1f70df,ghcr.io/graphql-hive/usage-ingestor:tuval_audit_log_api"
},
"webhooks": {
  "buildx.build.ref": "builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e/builder-7939324e-19d0-4f1c-b46d-6aaaacae0c9e0/od3wwvf0tz5k4zfc5ybu1dd5v",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
    "digest": "sha256:d4603f6f2e0758145a6ed7478ab495ff389c6448445cc662afc98ffcb31282f5",
    "size": 685
  },
  "containerimage.digest": "sha256:d4603f6f2e0758145a6ed7478ab495ff389c6448445cc662afc98ffcb31282f5",
  "image.name": "ghcr.io/graphql-hive/webhooks:51e1bff0cf454929938d132c53e5a58d9b1f70df,ghcr.io/graphql-hive/webhooks:tuval_audit_log_api"
}
}

@dotansimha dotansimha marked this pull request as draft September 3, 2024 20:24
@TuvalSimha TuvalSimha marked this pull request as ready for review September 4, 2024 16:50
@TuvalSimha TuvalSimha force-pushed the tuval/audit-log-api branch 2 times, most recently from de7bb4c to 2518d22 Compare September 8, 2024 14:27
@TuvalSimha TuvalSimha changed the title Draft: Audit log GraphQL API Audit log GraphQL API Sep 8, 2024
@TuvalSimha TuvalSimha force-pushed the tuval/audit-log-api branch 2 times, most recently from 005b64a to 01474f8 Compare September 18, 2024 07:08
@TuvalSimha TuvalSimha force-pushed the tuval/audit-log-api branch 2 times, most recently from 63f73bc to 037f9e2 Compare September 25, 2024 12:53
@TuvalSimha TuvalSimha force-pushed the tuval/audit-log-api branch 2 times, most recently from dab6855 to d030e2e Compare October 6, 2024 12:29
@TuvalSimha TuvalSimha force-pushed the tuval/audit-log-api branch 3 times, most recently from 405fe17 to be73910 Compare October 16, 2024 14:17
Copy link
Contributor

github-actions bot commented Oct 16, 2024

🚀 Snapshot Release (alpha)

The latest changes of this PR are available as alpha on npm (based on the declared changesets):

Package Version Info
@graphql-hive/apollo 0.36.2-alpha-20241016151134-9b6ada4170eda65cba3a13b5abe65e4f0f24d51d npm ↗︎ unpkg ↗︎
@graphql-hive/cli 0.44.2-alpha-20241016151134-9b6ada4170eda65cba3a13b5abe65e4f0f24d51d npm ↗︎ unpkg ↗︎
@graphql-hive/core 0.8.2-alpha-20241016151134-9b6ada4170eda65cba3a13b5abe65e4f0f24d51d npm ↗︎ unpkg ↗︎
@graphql-hive/envelop 0.33.10-alpha-20241016151134-9b6ada4170eda65cba3a13b5abe65e4f0f24d51d npm ↗︎ unpkg ↗︎
@graphql-hive/yoga 0.38.2-alpha-20241016151134-9b6ada4170eda65cba3a13b5abe65e4f0f24d51d npm ↗︎ unpkg ↗︎

user_email: z.string(),
organization_id: z.string(),
event_action: z.string(),
metadata: z.string().transform(x => JSON.parse(x)),
Copy link
Collaborator

@n1ru4l n1ru4l Oct 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there no model for the metadata? I think the metadata should be parsed in a safe way as well.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's just the transform, and then union discrimination validates it?
Is there another way to implement that with zod?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be fully modeled with zod types, something like this?

Suggested change
metadata: z.string().transform(x => JSON.parse(x)),
metadata: z.string().transform(x => MyModel.parse(JSON.parse(x)),

Comment on lines +42 to +58
injector.get(AuditLogManager).createLogAuditEvent(
{
eventType: 'SUBSCRIPTION_CREATED',
subscriptionCreatedAuditLogSchema: {
operations: args.input.monthlyLimits.operations,
paymentMethodId: args.input.paymentMethodId,
newPlan: 'PRO',
previousPlan: 'HOBBY',
},
},
{
organizationId: organizationId,
userEmail: currentUser.email,
userId: currentUser.id,
user: currentUser,
},
);
Copy link
Collaborator

@n1ru4l n1ru4l Oct 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These calls should happen within the business logic (BillingProvider), not the resolvers.

The resolvers should be as lean as possible and the audit event creation should be part of the business logic. This applies for all the audit log event creations.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm @n1ru4l it's a bit tricky, no?

Most of these providers are defined as Singleton scope, and I think this will prevent the provider from accessing other Operation scope providers? (for example, to get the current user)
(and alternative could be to change AuditLogProvider to be Operation?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example, I need to add this for each provider:

    private authManager: AuthManager,
    private auditLogManager: AuditLogManager,

@Injectable({
  global: true,
  scope: Scope.Singleton,
})
export class BillingProvider {
  private logger: Logger;
  private billingService;


  enabled = false;

  constructor(
    logger: Logger,
    private storage: Storage,
    private authManager: AuthManager,
    private auditLogManager: AuditLogManager,
    @Inject(BILLING_CONFIG) billingConfig: BillingConfig,
  ) {

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can make these non-singletons. I really want to avoid growing the resolvers with business logic. If we introduce a public API, that does not use GraphQL we have to duplicate all the audit log inserts.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think most of the *Manager classes are already Operation scoped, so it won't be an big issue. I agree with Laurin's take.
We may have a new GraphQL API or even OpenAPI in future and keeping things in resolvers means we need to move it anyway.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, when we do it in resolvers, the audit log needs to run after the business logic ran, otherwise we log something that did not happen

codegen setup

fix some

some

some

some

more

?

??

SOME?

??

?

fix some?

SOME

???

more

some some

test

fix some code review!

?

fix some

clean!

fix codegen path

???

?

??

?

?

added scope ti auditlogmanager

scheme publish & check & delete

members role

CLEAN MORE

target

project

prettier

fix resolver schema published

lint

fix code review!

?

?

prettier

migration

fix!

clean

fix filters

clean

??

?

resolve user

eventTime: e => e.event_time,

    scalar DateTime

  user: e => {

eventTime

clean

changes

Fix up mapper names and types.next imports

fix resolvers :)

clean all

lint

clean

sentry

fix some code review

more and more

Support && Laboratory Collection

CRUD query in collection

User role

org and target

fix code review

resolvers again!

prettier

clean

revert `inviteToOrganizationByEmail`

revert `updateSchemaPolicyForProject`

user invite

action for clickhouse
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants