-
Notifications
You must be signed in to change notification settings - Fork 110
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
feat: report usage with organization access tokens #6538
base: wip-organization-access-tokens
Are you sure you want to change the base?
feat: report usage with organization access tokens #6538
Conversation
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the 📝 WalkthroughSummary by CodeRabbit
WalkthroughThis pull request introduces new features and configuration enhancements across multiple services. Environment variables for PostgreSQL and Redis are added to the usage service configuration. New functions for creating organization access tokens are defined alongside comprehensive tests. In the API modules, permission sets are extended with a new “usage:report” value and associated permission groups are updated. Additionally, caching improvements and adjustments in dependency injection (such as the new TargetsCache) are implemented. The changes also include updated import paths, new type exports, and refined environment variable validations. Changes
Sequence Diagram(s)sequenceDiagram
participant T as Test Suite
participant F as Flow Module (createOrganizationAccessToken)
participant S as Seed Setup
participant G as GraphQL API
T->>F: Invoke createOrganizationAccessToken(input, authToken)
F->>G: Execute GraphQL mutation for token creation
G-->>F: Return token details (or error)
F-->>T: Deliver access token info
Note over S: createOrg integrates token creation for organization setup.
sequenceDiagram
participant C as Client
participant F as Fastify Server (target-id-route)
participant A as AuthN Strategy
participant TC as TargetsCache
participant RL as RateLimiter
participant UP as UsageProcessor
C->>F: POST /target/:targetId with token & payload
F->>F: Validate API version and check authorization header
F->>A: Authenticate session via OrganizationAccessTokenStrategy
A-->>F: Return session details with permissions
F->>TC: Retrieve target details by targetId
TC-->>F: Return target data (or 404 if not found)
F->>RL: Perform rate limit check
RL-->>F: Return status (allow/limit)
F->>UP: Process usage report (using token info)
UP-->>F: Return report outcome (success or error)
F-->>C: Respond with appropriate HTTP status and data
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
c43d033
to
5f7d975
Compare
🐋 This PR was built and pushed to the following Docker images: Targets: Platforms: Image Tag: Docker Bake metadata{
"app": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/api/health",
"build-arg:IMAGE_DESCRIPTION": "The app of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/app",
"build-arg:PORT": "3000",
"build-arg:RELEASE": "84d87306492f420c7ee4821c28f6c02bc360520b",
"build-arg:SERVICE_DIR_NAME": "@hive/app",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:dockerfile": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:shared": "vxrjwjb5pmqfycsf9d99o1qju"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-747ea4d5-49fc-41ef-b911-df1a6358f754/builder-747ea4d5-49fc-41ef-b911-df1a6358f7540/376skf4e3erfmnsvkraqmf29t",
"containerimage.config.digest": "sha256:0ba35a6116871e496eaa3575a924e0a94d23ff81b2e9ac14a1ffd880e831d41d",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:72bbacca08e6ee9235993bf7ad3a707a36db15843b158e1f1cd491ddc57c5055",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:72bbacca08e6ee9235993bf7ad3a707a36db15843b158e1f1cd491ddc57c5055",
"image.name": "ghcr.io/graphql-hive/app:84d87306492f420c7ee4821c28f6c02bc360520b-amd64,ghcr.io/graphql-hive/app:feat_report_usage_with_organization_access_token-amd64"
},
"buildx.build.warnings": [
{
"vertex": "sha256:54fe4fb3048c2bed1b68a85b8b763eeb752667e662d4239fcb1d19b48c9c4497",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRSRUxFQVNFJyAobGluZSAxMyk=",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 13
},
"end": {
"line": 13
}
}
]
},
{
"vertex": "sha256:54fe4fb3048c2bed1b68a85b8b763eeb752667e662d4239fcb1d19b48c9c4497",
"level": 1,
"short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDIwKQ==",
"detail": [
"TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
],
"url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 20
},
"end": {
"line": 20
}
}
]
},
{
"vertex": "sha256:7cb197a67621a6f966ab4c672e9e2ff40eb7b2e4199131d12575802cdc05d578",
"level": 1,
"short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDEwKQ==",
"detail": [
"TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
],
"url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
"sourceInfo": {
"filename": "migrations.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 10
},
"end": {
"line": 10
}
}
]
},
{
"vertex": "sha256:7cb197a67621a6f966ab4c672e9e2ff40eb7b2e4199131d12575802cdc05d578",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9ERVNDUklQVElPTicgKGxpbmUgMTcp",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "migrations.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 17
},
"end": {
"line": 17
}
}
]
},
{
"vertex": "sha256:54fe4fb3048c2bed1b68a85b8b763eeb752667e662d4239fcb1d19b48c9c4497",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9ERVNDUklQVElPTicgKGxpbmUgMTQp",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 14
},
"end": {
"line": 14
}
}
]
},
{
"vertex": "sha256:54fe4fb3048c2bed1b68a85b8b763eeb752667e662d4239fcb1d19b48c9c4497",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRSRUxFQVNFJyAobGluZSAyMSk=",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 21
},
"end": {
"line": 21
}
}
]
},
{
"vertex": "sha256:54fe4fb3048c2bed1b68a85b8b763eeb752667e662d4239fcb1d19b48c9c4497",
"level": 1,
"short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDIyKQ==",
"detail": [
"TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
],
"url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 22
},
"end": {
"line": 22
}
}
]
},
{
"vertex": "sha256:7cb197a67621a6f966ab4c672e9e2ff40eb7b2e4199131d12575802cdc05d578",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRSRUxFQVNFJyAobGluZSAxMik=",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "migrations.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 12
},
"end": {
"line": 12
}
}
]
},
{
"vertex": "sha256:7cb197a67621a6f966ab4c672e9e2ff40eb7b2e4199131d12575802cdc05d578",
"level": 1,
"short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDEyKQ==",
"detail": [
"TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
],
"url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
"sourceInfo": {
"filename": "migrations.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 12
},
"end": {
"line": 12
}
}
]
},
{
"vertex": "sha256:7cb197a67621a6f966ab4c672e9e2ff40eb7b2e4199131d12575802cdc05d578",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9USVRMRScgKGxpbmUgMTUp",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "migrations.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 15
},
"end": {
"line": 15
}
}
]
},
{
"vertex": "sha256:54fe4fb3048c2bed1b68a85b8b763eeb752667e662d4239fcb1d19b48c9c4497",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9USVRMRScgKGxpbmUgMTIp",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 12
},
"end": {
"line": 12
}
}
]
},
{
"vertex": "sha256:54fe4fb3048c2bed1b68a85b8b763eeb752667e662d4239fcb1d19b48c9c4497",
"level": 1,
"short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDIxKQ==",
"detail": [
"TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
],
"url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 21
},
"end": {
"line": 21
}
}
]
},
{
"vertex": "sha256:54fe4fb3048c2bed1b68a85b8b763eeb752667e662d4239fcb1d19b48c9c4497",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRQT1JUJyAobGluZSAyMik=",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 22
},
"end": {
"line": 22
}
}
]
},
{
"vertex": "sha256:7cb197a67621a6f966ab4c672e9e2ff40eb7b2e4199131d12575802cdc05d578",
"level": 1,
"short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDExKQ==",
"detail": [
"TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
],
"url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
"sourceInfo": {
"filename": "migrations.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 11
},
"end": {
"line": 11
}
}
]
}
],
"composition-federation-2": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "Federation 2 Composition Service for GraphQL Hive.",
"build-arg:IMAGE_TITLE": "graphql-hive/composition-federation-2",
"build-arg:PORT": "3069",
"build-arg:RELEASE": "84d87306492f420c7ee4821c28f6c02bc360520b",
"build-arg:SERVICE_DIR_NAME": "@hive/external-composition",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:dockerfile": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:shared": "vxrjwjb5pmqfycsf9d99o1qju"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-747ea4d5-49fc-41ef-b911-df1a6358f754/builder-747ea4d5-49fc-41ef-b911-df1a6358f7540/v1180pthlp2j7rkb44yvgbcne",
"containerimage.config.digest": "sha256:4d771f821d57826c05874a9d9f6c8382ca8d5f749c813706e60de6bc3b12d867",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:d908b950f32d3e260d22d90eee87dc6cb6b3e42a7330f3adfe6aa5ac7d93493f",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:d908b950f32d3e260d22d90eee87dc6cb6b3e42a7330f3adfe6aa5ac7d93493f",
"image.name": "ghcr.io/graphql-hive/composition-federation-2:84d87306492f420c7ee4821c28f6c02bc360520b-amd64,ghcr.io/graphql-hive/composition-federation-2:feat_report_usage_with_organization_access_token-amd64"
},
"emails": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The emails service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/emails",
"build-arg:PORT": "3006",
"build-arg:RELEASE": "84d87306492f420c7ee4821c28f6c02bc360520b",
"build-arg:SERVICE_DIR_NAME": "@hive/emails",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:dockerfile": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:shared": "vxrjwjb5pmqfycsf9d99o1qju"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-747ea4d5-49fc-41ef-b911-df1a6358f754/builder-747ea4d5-49fc-41ef-b911-df1a6358f7540/9qi59y7pmvwdx76dwvqzf88ti",
"containerimage.config.digest": "sha256:b0a2bd9875895acf50670f5c3874a74c5ae970d28bd9c41aa1124b6f3481a707",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:cf3dd32819f1ef18f63df2ac93adbdd6163c77462b845ae971e122a87796333c",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:cf3dd32819f1ef18f63df2ac93adbdd6163c77462b845ae971e122a87796333c",
"image.name": "ghcr.io/graphql-hive/emails:84d87306492f420c7ee4821c28f6c02bc360520b-amd64,ghcr.io/graphql-hive/emails:feat_report_usage_with_organization_access_token-amd64"
},
"policy": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The policy service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/policy",
"build-arg:PORT": "3012",
"build-arg:RELEASE": "84d87306492f420c7ee4821c28f6c02bc360520b",
"build-arg:SERVICE_DIR_NAME": "@hive/policy",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:dockerfile": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:shared": "vxrjwjb5pmqfycsf9d99o1qju"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-747ea4d5-49fc-41ef-b911-df1a6358f754/builder-747ea4d5-49fc-41ef-b911-df1a6358f7540/grrswz93k88vkim7v7ycrrfw5",
"containerimage.config.digest": "sha256:0a4e7404e766e612e16e9ad46269eca83c801e6219c15c36a1f01c3eb978d096",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:3171d9f465f67e6bd2089f3371ee432d3b692411ce70a0895c4ca21ba7d03355",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:3171d9f465f67e6bd2089f3371ee432d3b692411ce70a0895c4ca21ba7d03355",
"image.name": "ghcr.io/graphql-hive/policy:84d87306492f420c7ee4821c28f6c02bc360520b-amd64,ghcr.io/graphql-hive/policy:feat_report_usage_with_organization_access_token-amd64"
},
"rate-limit": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The rate limit service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/rate-limit",
"build-arg:PORT": "3009",
"build-arg:RELEASE": "84d87306492f420c7ee4821c28f6c02bc360520b",
"build-arg:SERVICE_DIR_NAME": "@hive/rate-limit",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:dockerfile": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:shared": "vxrjwjb5pmqfycsf9d99o1qju"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-747ea4d5-49fc-41ef-b911-df1a6358f754/builder-747ea4d5-49fc-41ef-b911-df1a6358f7540/pilfpnlymx22w2d90cfn29fuk",
"containerimage.config.digest": "sha256:0599307072610a9e76e627d081ad89b68f3ca93a768bd28cd3ba010bce045b14",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:d35f85b58c0a178e8428efd0f688733762b793c9e8a00b63e3c47274b643836d",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:d35f85b58c0a178e8428efd0f688733762b793c9e8a00b63e3c47274b643836d",
"image.name": "ghcr.io/graphql-hive/rate-limit:84d87306492f420c7ee4821c28f6c02bc360520b-amd64,ghcr.io/graphql-hive/rate-limit:feat_report_usage_with_organization_access_token-amd64"
},
"schema": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The schema service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/schema",
"build-arg:PORT": "3002",
"build-arg:RELEASE": "84d87306492f420c7ee4821c28f6c02bc360520b",
"build-arg:SERVICE_DIR_NAME": "@hive/schema",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:dockerfile": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:shared": "vxrjwjb5pmqfycsf9d99o1qju"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-747ea4d5-49fc-41ef-b911-df1a6358f754/builder-747ea4d5-49fc-41ef-b911-df1a6358f7540/ipc83n893yict8prkb21qiuko",
"containerimage.config.digest": "sha256:47b773ccff7c9ab395bdd3bea020c935058ba24f63ced345923469e0b78e6316",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:f09166347977dadc43bd88ce5409d4683da5b88c051ba83c932c36156af1d0b6",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:f09166347977dadc43bd88ce5409d4683da5b88c051ba83c932c36156af1d0b6",
"image.name": "ghcr.io/graphql-hive/schema:84d87306492f420c7ee4821c28f6c02bc360520b-amd64,ghcr.io/graphql-hive/schema:feat_report_usage_with_organization_access_token-amd64"
},
"server": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The server service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/server",
"build-arg:PORT": "3001",
"build-arg:RELEASE": "84d87306492f420c7ee4821c28f6c02bc360520b",
"build-arg:SERVICE_DIR_NAME": "@hive/server",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:dockerfile": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:shared": "vxrjwjb5pmqfycsf9d99o1qju"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-747ea4d5-49fc-41ef-b911-df1a6358f754/builder-747ea4d5-49fc-41ef-b911-df1a6358f7540/t1rk1uqi4kf12danmu1834qiu",
"containerimage.config.digest": "sha256:9fe6b97c4f58a14d6ddc80ce8425948755892411c1fa1f019492c1f96196bdeb",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:500a1ae2146d5b2c3eb5e0e615affaed360c02407584917af69c22955ee52b16",
"size": 2076,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:500a1ae2146d5b2c3eb5e0e615affaed360c02407584917af69c22955ee52b16",
"image.name": "ghcr.io/graphql-hive/server:84d87306492f420c7ee4821c28f6c02bc360520b-amd64,ghcr.io/graphql-hive/server:feat_report_usage_with_organization_access_token-amd64"
},
"storage": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "migrations.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:IMAGE_DESCRIPTION": "The migrations service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/storage",
"build-arg:RELEASE": "84d87306492f420c7ee4821c28f6c02bc360520b",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:dockerfile": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:shared": "vxrjwjb5pmqfycsf9d99o1qju"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-747ea4d5-49fc-41ef-b911-df1a6358f754/builder-747ea4d5-49fc-41ef-b911-df1a6358f7540/jgbksnfndnp34c6o814ls8xzm",
"containerimage.config.digest": "sha256:b8731977039db64958ad36f417dbb359c11165481c987182295b453095843e5b",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:655dd79909c57925527cd9c79b94315215d559a5b1a59d233b03903c875f8da3",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:655dd79909c57925527cd9c79b94315215d559a5b1a59d233b03903c875f8da3",
"image.name": "ghcr.io/graphql-hive/storage:84d87306492f420c7ee4821c28f6c02bc360520b-amd64,ghcr.io/graphql-hive/storage:feat_report_usage_with_organization_access_token-amd64"
},
"stripe-billing": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The stripe billing service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/stripe-billing",
"build-arg:PORT": "3010",
"build-arg:RELEASE": "84d87306492f420c7ee4821c28f6c02bc360520b",
"build-arg:SERVICE_DIR_NAME": "@hive/stripe-billing",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:dockerfile": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:shared": "vxrjwjb5pmqfycsf9d99o1qju"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-747ea4d5-49fc-41ef-b911-df1a6358f754/builder-747ea4d5-49fc-41ef-b911-df1a6358f7540/7pa7zsw8wod0u9sfcdbhtm5um",
"containerimage.config.digest": "sha256:243efabcd545db150731d3ebb41380907cd0950e0a531a9a97368aca3bf0047a",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:aab4f943e776a8e7cc47d187b3c5c117810907fd178030fa78c97c438e2f84bf",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:aab4f943e776a8e7cc47d187b3c5c117810907fd178030fa78c97c438e2f84bf",
"image.name": "ghcr.io/graphql-hive/stripe-billing:84d87306492f420c7ee4821c28f6c02bc360520b-amd64,ghcr.io/graphql-hive/stripe-billing:feat_report_usage_with_organization_access_token-amd64"
},
"tokens": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The tokens service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/tokens",
"build-arg:PORT": "3003",
"build-arg:RELEASE": "84d87306492f420c7ee4821c28f6c02bc360520b",
"build-arg:SERVICE_DIR_NAME": "@hive/tokens",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:dockerfile": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:shared": "vxrjwjb5pmqfycsf9d99o1qju"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-747ea4d5-49fc-41ef-b911-df1a6358f754/builder-747ea4d5-49fc-41ef-b911-df1a6358f7540/ovtlcjaax3dyjhor2gsuq2s6v",
"containerimage.config.digest": "sha256:ae2e0d98761cb8d7ea055ea002a07b9afe0119159b11fb523f7a4df69a05c518",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:e0e1b70910d356eee464feac1c0fcca07642e76f9ffe3fa9def63ad62dc12707",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:e0e1b70910d356eee464feac1c0fcca07642e76f9ffe3fa9def63ad62dc12707",
"image.name": "ghcr.io/graphql-hive/tokens:84d87306492f420c7ee4821c28f6c02bc360520b-amd64,ghcr.io/graphql-hive/tokens:feat_report_usage_with_organization_access_token-amd64"
},
"usage": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The usage ingestor service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/usage",
"build-arg:PORT": "3006",
"build-arg:RELEASE": "84d87306492f420c7ee4821c28f6c02bc360520b",
"build-arg:SERVICE_DIR_NAME": "@hive/usage",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:dockerfile": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:shared": "vxrjwjb5pmqfycsf9d99o1qju"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-747ea4d5-49fc-41ef-b911-df1a6358f754/builder-747ea4d5-49fc-41ef-b911-df1a6358f7540/sx1eacp44ywvten4gablmcrgu",
"containerimage.config.digest": "sha256:ea229619e429155e8357d0f0efb0a2d2314cab8909aa75ec3cea129ef119f7d3",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:5f39ef7c4715a477c8ac1229f2b5f752cfbc56a19a18a8e90b3a5048fad78d1b",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:5f39ef7c4715a477c8ac1229f2b5f752cfbc56a19a18a8e90b3a5048fad78d1b",
"image.name": "ghcr.io/graphql-hive/usage:84d87306492f420c7ee4821c28f6c02bc360520b-amd64,ghcr.io/graphql-hive/usage:feat_report_usage_with_organization_access_token-amd64"
},
"usage-estimator": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The usage estimator service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/usage-estimator",
"build-arg:PORT": "3008",
"build-arg:RELEASE": "84d87306492f420c7ee4821c28f6c02bc360520b",
"build-arg:SERVICE_DIR_NAME": "@hive/usage-estimator",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:dockerfile": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:shared": "vxrjwjb5pmqfycsf9d99o1qju"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-747ea4d5-49fc-41ef-b911-df1a6358f754/builder-747ea4d5-49fc-41ef-b911-df1a6358f7540/gm4akb0a2gy7xii63dsskg0z2",
"containerimage.config.digest": "sha256:18e446200ab79ab7dd8015c89154037684a0ed1a17112804b5f7aef9ec0722cf",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:f956e18b2ec9cbd92b18a331c718e19508ac7861c5c1df2ae595fc90a5d614d2",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:f956e18b2ec9cbd92b18a331c718e19508ac7861c5c1df2ae595fc90a5d614d2",
"image.name": "ghcr.io/graphql-hive/usage-estimator:84d87306492f420c7ee4821c28f6c02bc360520b-amd64,ghcr.io/graphql-hive/usage-estimator:feat_report_usage_with_organization_access_token-amd64"
},
"usage-ingestor": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The usage ingestor service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/usage-ingestor",
"build-arg:PORT": "3007",
"build-arg:RELEASE": "84d87306492f420c7ee4821c28f6c02bc360520b",
"build-arg:SERVICE_DIR_NAME": "@hive/usage-ingestor",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:dockerfile": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:shared": "vxrjwjb5pmqfycsf9d99o1qju"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-747ea4d5-49fc-41ef-b911-df1a6358f754/builder-747ea4d5-49fc-41ef-b911-df1a6358f7540/ixvm7vi7if5vv1q9dpy27683w",
"containerimage.config.digest": "sha256:d70ea10fd9d5add7d633f2781bcf21536f633acfdea99b261fa32cc57e0e71f3",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:9953e38403e1332939df7764a446f9accbe8f7e3a9b236faf3b4c2beabd08015",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:9953e38403e1332939df7764a446f9accbe8f7e3a9b236faf3b4c2beabd08015",
"image.name": "ghcr.io/graphql-hive/usage-ingestor:84d87306492f420c7ee4821c28f6c02bc360520b-amd64,ghcr.io/graphql-hive/usage-ingestor:feat_report_usage_with_organization_access_token-amd64"
},
"webhooks": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The webhooks ingestor service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/webhooks",
"build-arg:PORT": "3005",
"build-arg:RELEASE": "84d87306492f420c7ee4821c28f6c02bc360520b",
"build-arg:SERVICE_DIR_NAME": "@hive/webhooks",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:dockerfile": "vxrjwjb5pmqfycsf9d99o1qju",
"local-sessionid:shared": "vxrjwjb5pmqfycsf9d99o1qju"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-747ea4d5-49fc-41ef-b911-df1a6358f754/builder-747ea4d5-49fc-41ef-b911-df1a6358f7540/aq6ha3ywx0ws01q7kjp43r67l",
"containerimage.config.digest": "sha256:fabd97a19ad12817b777dfcd5e7bf3664e332765d4c05c023fb99455ee6fb17c",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:cdf9247aa89ca03754f252f8c49bedb8e9b9f80f811bb4b7e7d3545539bc1d32",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:cdf9247aa89ca03754f252f8c49bedb8e9b9f80f811bb4b7e7d3545539bc1d32",
"image.name": "ghcr.io/graphql-hive/webhooks:84d87306492f420c7ee4821c28f6c02bc360520b-amd64,ghcr.io/graphql-hive/webhooks:feat_report_usage_with_organization_access_token-amd64"
}
} |
2b12c5d
to
4504512
Compare
4504512
to
682f9a8
Compare
"@hive/api/src/modules/schema/providers/artifact-storage-reader": [ | ||
"./packages/services/api/src/modules/schema/providers/artifact-storage-reader.ts" | ||
], | ||
"@hive/api/src/modules/shared/providers/redis": [ | ||
"./packages/services/api/src/modules/shared/providers/redis.ts" | ||
], | ||
"@hive/api/src/modules/shared/providers/pub-sub": [ | ||
"./packages/services/api/src/modules/shared/providers/pub-sub.ts" | ||
], | ||
|
||
"@hive/api/*": ["./packages/services/api/src/*"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Allowing wildcard imports seemed to be more flexible until we figure out how we want to organize shared dependencies (e.g. break them into their own packages).
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (13)
packages/services/api/src/modules/target/providers/targets-cache.ts (2)
30-50
: Consider a fallback if Redis connectivity is lost.
Currently, it's unclear how the system behaves if Redis becomes unavailable at runtime. You might want to implement a fallback (e.g., memory-only) or a configurable circuit breaker mechanism to avoid partial outages or degraded performance.
53-63
: Negative caching risk.
WhenfindTargetById
returnsnull
, thisnull
result may be cached for up to 5 minutes (with an additional 24-hour grace). This could prevent a newly created target with the same ID from being recognized within that period. Consider separate TTLs for null results or a short-circuiting approach for negative caching to avoid stale data issues.packages/services/usage/src/target-id-route.ts (1)
66-77
: Consider using 400 or 422 instead of 401 for invalid API version.
HTTP 401 often implies invalid or missing credentials. An HTTP 400 or 422 might be more appropriate to indicate a malformed or unacceptable header value in this context.- await reply.status(401).send("Invalid 'x-api-version' header value."); + await reply.status(400).send("Invalid 'x-api-version' header value.");packages/services/usage/src/index.ts (3)
91-95
: Potential concurrency concerns with a small connection pool.
You're initializing the PostgreSQL pool with a max pool size of5
, which might be insufficient under higher loads. Consider increasing it or making it configurable to handle spikes in query volume.
97-105
: Direct injection of Redis and PG pool intoTargetsCache
.
While this works, it can couple the cache layer tightly to these dependencies. Consider a separate caching interface abstraction for more flexible testing and future changes (e.g., switching to a different cache provider).
109-134
: Logging level for Redis events.
All Redis events are logged at runtime, which is helpful for debugging but can clutter logs in production. Consider adjusting log levels (e.g., using.debug
for reconnections) to balance observability with verbosity.packages/services/usage/src/authn.ts (1)
13-37
: Add input validation for required arguments.While the implementation is solid, consider adding validation for the required arguments to ensure they are properly initialized.
export function createAuthN(args: { pgPool: DatabasePool; redis: Redis; isPrometheusEnabled: boolean; }): AuthN { + if (!args.pgPool) { + throw new Error('PostgreSQL pool is required'); + } + if (!args.redis) { + throw new Error('Redis instance is required'); + } const prometheusConfig = new PrometheusConfig(args.isPrometheusEnabled);integration-tests/tests/usage-reporting/organization-access-token.spec.ts (3)
26-53
: Consider extracting duplicate request payload to a helper function.The same request payload structure is repeated across all three tests. Consider extracting it to a helper function to improve maintainability and reduce duplication.
function createUsagePayload() { return { size: 1, map: { c3b6d9b0: { operationName: 'me', operation: 'query me { me { id name } }', fields: ['Query', 'Query.me', 'User', 'User.id', 'User.name'], }, }, operations: [ { operationMapKey: 'c3b6d9b0', timestamp: Date.now(), // Use dynamic timestamp execution: { ok: true, duration: 150000000, errorsTotal: 0, }, metadata: { client: { name: 'demo', version: '0.0.1', }, }, }, ], }; }Also applies to: 94-121, 168-195
38-38
: Consider using dynamic timestamp instead of hardcoded value.The timestamp
1663158676535
is hardcoded. Consider usingDate.now()
for a more realistic test scenario.Also applies to: 106-106, 180-180
41-41
: Add comment explaining the duration value.The duration value
150000000
appears to be in nanoseconds. Consider adding a comment explaining the unit or using a constant with a descriptive name.const OPERATION_DURATION_NS = 150_000_000; // 150ms in nanosecondsAlso applies to: 109-109, 183-183
integration-tests/testkit/seed.ts (1)
114-136
: Enhance error handling with more specific error types.While the implementation is solid, consider improving error handling by:
- Creating specific error types for different failure cases
- Including more details in the error message
- if (result.createOrganizationAccessToken.error) { - throw new Error(result.createOrganizationAccessToken.error.message); + const error = result.createOrganizationAccessToken.error; + if (error) { + throw new Error( + `Failed to create organization access token: ${error.message}` + + (error.details ? + `\nTitle: ${error.details.title}\nDescription: ${error.details.description}` + : '') + ); + }packages/services/storage/src/index.ts (1)
5134-5159
: LGTM! Consider adding JSDoc documentation.The implementation is well-structured, type-safe, and follows best practices. Consider adding JSDoc documentation to describe the function's purpose, parameters, and return type.
+/** + * Finds a target by its ID and returns the target with organization ID. + * @param deps - Dependencies object containing database pool + * @param deps.pool - Database pool instance + * @returns A function that takes a target ID and returns a Promise of Target or null + */ export function findTargetById(deps: { pool: DatabasePool }) {packages/services/usage/README.md (1)
32-32
: Minor Style Suggestion on Configuration Descriptions
In the configuration table, consider replacing "User name" with "Username" for thePOSTGRES_USER
description to align with modern conventions and improve clarity.🧰 Tools
🪛 LanguageTool
[style] ~32-~32: It’s more common nowadays to write this noun as one word.
Context: ..._USER` | Yes | User name for accessing the postgres database. ...(RECOMMENDED_COMPOUNDS)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (27)
docker/docker-compose.community.yml
(1 hunks)integration-tests/testkit/flow.ts
(2 hunks)integration-tests/testkit/seed.ts
(2 hunks)integration-tests/tests/usage-reporting/organization-access-token.spec.ts
(1 hunks)packages/services/api/src/modules/auth/lib/authz.ts
(1 hunks)packages/services/api/src/modules/auth/lib/organization-access-token-strategy.ts
(1 hunks)packages/services/api/src/modules/organization/lib/organization-access-token-permissions.ts
(1 hunks)packages/services/api/src/modules/organization/lib/organization-member-permissions.ts
(1 hunks)packages/services/api/src/modules/organization/providers/organization-access-tokens-cache.ts
(3 hunks)packages/services/api/src/modules/target/index.ts
(2 hunks)packages/services/api/src/modules/target/providers/target-manager.ts
(3 hunks)packages/services/api/src/modules/target/providers/targets-cache.ts
(1 hunks)packages/services/server/src/index.ts
(1 hunks)packages/services/storage/package.json
(1 hunks)packages/services/storage/src/index.ts
(1 hunks)packages/services/usage/.env.template
(1 hunks)packages/services/usage/README.md
(1 hunks)packages/services/usage/package.json
(2 hunks)packages/services/usage/src/authn.ts
(1 hunks)packages/services/usage/src/environment.ts
(4 hunks)packages/services/usage/src/index.ts
(7 hunks)packages/services/usage/src/metric-helper.ts
(1 hunks)packages/services/usage/src/rate-limit.ts
(1 hunks)packages/services/usage/src/target-id-route.ts
(1 hunks)packages/services/usage/src/usage-processor-2.ts
(6 hunks)packages/services/usage/src/usage.ts
(1 hunks)tsconfig.json
(2 hunks)
✅ Files skipped from review due to trivial changes (1)
- packages/services/server/src/index.ts
🧰 Additional context used
📓 Path-based instructions (3)
`packages/services/**`: Microservices written in NodeJS and ...
packages/services/**
: Microservices written in NodeJS and TypeScript. Most of the dirs under this directory are packages and deployed as Docker packages.
Interaction between services is done using tRPC.
We prefer writing code that does input/output validations with Zod.
The directories that ends with-worker
are projects that are built on top of CloudFlare Workers infrastructure and deployed there.
Thecdn-worker
is a special one, it serves a high-available, detached CDN on CloudFlare Workers. This is how our end-users fetches the crucial data from our platform, in a way that does not depend/couple on our main API (served as GraphQL API).
packages/services/api/src/modules/auth/lib/authz.ts
packages/services/usage/src/rate-limit.ts
packages/services/api/src/modules/target/index.ts
packages/services/usage/src/usage.ts
packages/services/api/src/modules/organization/lib/organization-member-permissions.ts
packages/services/api/src/modules/organization/lib/organization-access-token-permissions.ts
packages/services/api/src/modules/auth/lib/organization-access-token-strategy.ts
packages/services/usage/package.json
packages/services/usage/src/environment.ts
packages/services/usage/src/target-id-route.ts
packages/services/api/src/modules/target/providers/target-manager.ts
packages/services/usage/src/metric-helper.ts
packages/services/usage/src/authn.ts
packages/services/usage/README.md
packages/services/storage/src/index.ts
packages/services/usage/src/usage-processor-2.ts
packages/services/usage/src/index.ts
packages/services/storage/package.json
packages/services/api/src/modules/target/providers/targets-cache.ts
packages/services/api/src/modules/organization/providers/organization-access-tokens-cache.ts
`integration-tests/**`: integration tests for ensuring featu...
integration-tests/**
: integration tests for ensuring features and important flows are running. Usually, changes to thepackages/
directory will affect this. In ideal flow, each PR should include integration tests.
integration-tests/testkit/seed.ts
integration-tests/testkit/flow.ts
integration-tests/tests/usage-reporting/organization-access-token.spec.ts
`**/.env.template`: When a `.env.template` file changes, it'...
**/.env.template
: When a.env.template
file changes, it's usually because we added/removed an environment variable from a service.
Please ensure that the service'sREADME.md
file also includes changes to reflect the changes.
Also, make sure that all Docker Compose file that are using the service are also up to date with default values.
Also validate indeployment/
directory that the service's IaC deployment code is up to date.
packages/services/usage/.env.template
🪛 LanguageTool
packages/services/usage/README.md
[style] ~32-~32: It’s more common nowadays to write this noun as one word.
Context: ..._USER` | Yes | User name for accessing the postgres database. ...
(RECOMMENDED_COMPOUNDS)
🔇 Additional comments (34)
packages/services/api/src/modules/target/providers/targets-cache.ts (1)
65-69
: Cache purge method looks correct.
Thepurge
implementation appropriately removes the target entry. No issues identified here.packages/services/usage/src/target-id-route.ts (2)
174-185
: Ensure limited retry attempts for 503 status.
Returning a 503 status instructs upstream gateways to retry. To avoid potential infinite retry loops, ensure external callers or gateway layers set a retry limit or back-off strategy.
205-235
: Robust error handling for usage parsing.
The method properly validates the incoming usage report, sends a 400 on validation failure, and logs relevant diagnostics. This design helps ensure secure and predictable outcomes even for malformed requests.packages/services/usage/src/index.ts (1)
72-81
: Validate Redis behavior on readiness checks.
enableReadyCheck: false
can speed up connection time but may mask connectivity issues or partial failures. Consider re-enabling it or verifying that your fallback/error-handling logic is robust enough to handle connection interruptions.packages/services/api/src/modules/target/index.ts (1)
3-3
: LGTM! Good addition of caching mechanism.The addition of
TargetsCache
to the providers array is a good enhancement that will improve performance through caching.Also applies to: 12-12
packages/services/usage/src/metric-helper.ts (2)
4-16
: LGTM! Well-structured error handling and performance measurement.The implementation includes:
- Proper error handling with Sentry integration
- Timer cleanup in finally block
- Type-safe generic parameter
18-28
: LGTM! Well-structured async handler with performance measurement.The implementation includes:
- Proper async/await usage
- Timer cleanup in finally block
- Type-safe generic parameters
packages/services/usage/src/authn.ts (1)
1-37
: LGTM! Well-structured authentication provider setup.The implementation follows good practices:
- Proper dependency injection
- Clear separation of concerns
- Type-safe implementation
packages/services/api/src/modules/organization/lib/organization-access-token-permissions.ts (1)
26-36
: LGTM! Well-structured permission group for usage reporting.The new permission group follows the established pattern and provides clear descriptions for the permissions.
packages/services/api/src/modules/organization/providers/organization-access-tokens-cache.ts (3)
5-5
: LGTM! Improved type safety with Redis import.The change from value import to type import is correct since Redis is only used as a type.
24-28
: LGTM! Better encapsulation with private pool.Good improvement in the constructor by making the pool parameter private and removing the unused logger parameter.
53-61
: LGTM! Enhanced logging with request context.The modification to pass the logger through the
get
method is a good practice as it maintains the request context for logging.packages/services/api/src/modules/auth/lib/organization-access-token-strategy.ts (1)
86-89
: LGTM! Consistent logger propagation.The addition of the logger parameter aligns with the changes in OrganizationAccessTokensCache, maintaining request context in logs.
packages/services/usage/src/rate-limit.ts (1)
151-151
: LGTM! Enhanced type safety with UsageRateLimit export.Good addition of the exported type which improves type safety and documentation for consumers of the module.
packages/services/usage/src/environment.ts (2)
113-114
: LGTM!The configuration parsing follows the established pattern and is consistent with the rest of the codebase.
202-215
: LGTM!The configuration exports follow the established pattern and are consistent with the rest of the codebase.
packages/services/api/src/modules/organization/lib/organization-member-permissions.ts (1)
268-268
: LGTM!The addition of
usage:report
to the list of CLI-only actions is consistent with the PR objectives of enhancing usage reporting functionality.packages/services/usage/src/usage.ts (1)
323-323
: LGTM!The
Usage
type export enhances type safety and clarity when using thecreateUsage
function. UsingReturnType
ensures the type stays in sync with any changes to the function's return type.packages/services/api/src/modules/target/providers/target-manager.ts (3)
12-12
: LGTM!The import of
TargetsCache
is correctly placed and consistent with the PR objectives.
34-34
: LGTM!The addition of
targetsCache
parameter is correctly implemented and consistent with the PR objectives.
137-138
: LGTM!The cache purge is correctly placed after the target deletion to ensure cache consistency.
packages/services/api/src/modules/auth/lib/authz.ts (1)
371-371
: LGTM! New permission follows security best practices.The
usage:report
permission is correctly added at the target level, following the established permission naming convention and scope hierarchy.packages/services/usage/src/usage-processor-2.ts (3)
18-22
: LGTM! Attribute initialization is type-safe and consistent.The initialization of attributes correctly uses the new token structure with explicit ID fields.
34-38
: LGTM! Token type definition is explicit and well-structured.The inline type definition clearly specifies the required fields with appropriate types.
88-89
: LGTM! Report object construction uses correct token fields.The report object correctly uses targetId and organizationId from the new token structure.
integration-tests/testkit/flow.ts (1)
1496-1529
: LGTM! Well-structured token creation implementation.The createOrganizationAccessToken function:
- Follows established patterns
- Handles both success and error cases
- Returns comprehensive token information
- Uses proper GraphQL error handling
packages/services/storage/src/index.ts (2)
5161-5171
: LGTM! Models are well-defined and type-safe.The Zod models are properly structured with appropriate types and validation. The extension pattern for
TargetWithOrgIdModel
is a clean way to add the organization ID field.
5126-5132
: LGTM! SQL fields are well-defined with proper aliases.The SQL field selection is comprehensive and follows best practices with proper field aliasing and naming conventions.
packages/services/usage/.env.template (1)
8-17
: New PostgreSQL and Redis Environment Variables Added
The new environment variables for PostgreSQL (POSTGRES_USER
,POSTGRES_PASSWORD
,POSTGRES_HOST
,POSTGRES_PORT
, andPOSTGRES_DB
) and Redis (REDIS_HOST
,REDIS_PORT
, andREDIS_PASSWORD
) are clearly integrated. Please ensure that the quoting style is consistent across all entries (for example, some values are wrapped in quotes while others are not) so that downstream parsers or scripts do not encounter unexpected behavior.packages/services/usage/package.json (1)
12-14
: New Dependencies for Enhanced Functionality
The additions of"@hive/api": "workspace:*"
,"@hive/storage": "workspace:*"
,"ioredis": "5.4.2"
, and"reflect-metadata": "^0.2.0"
support the integration of PostgreSQL and Redis connectivity as well as enrich the service’s capabilities. Please verify that these libraries are intended for runtime use; if so, consider moving them fromdevDependencies
todependencies
to ensure they are bundled appropriately in production.Also applies to: 25-30
packages/services/storage/package.json (1)
11-13
: New Export for DB Pool Module
The addition of the export entry"./db/pool": "./src/db/pool.ts"
enables consumers to import the database pool functionality directly, which enhances modularity. Ensure that this module is adequately documented so that downstream developers understand its purpose and usage.tsconfig.json (1)
28-29
: Streamlined Module Path Mappings
The updated path mappings—updating"@hive/api/*"
to reference all files under./packages/services/api/src/*
and adding"@hive/storage/*"
to cover all files under./packages/services/storage/src/*
—simplify module resolution and provide greater flexibility in imports. Kindly verify that all consumers of these modules have been updated and that this change does not inadvertently introduce ambiguous resolutions.Also applies to: 55-56
packages/services/usage/README.md (1)
28-37
: Enhanced Configuration Documentation for PostgreSQL and Redis
The README now documents the new configuration parameters for PostgreSQL (includingPOSTGRES_SSL
,POSTGRES_HOST
,POSTGRES_PORT
,POSTGRES_DB
,POSTGRES_USER
, andPOSTGRES_PASSWORD
) and for Redis (REDIS_HOST
,REDIS_PORT
,REDIS_PASSWORD
, andREDIS_TLS_ENABLED
) clearly. Please ensure that the defaults here remain consistent with those in the.env.template
and the Docker Compose files, and consider including examples or additional context for any TLS-related settings.🧰 Tools
🪛 LanguageTool
[style] ~32-~32: It’s more common nowadays to write this noun as one word.
Context: ..._USER` | Yes | User name for accessing the postgres database. ...(RECOMMENDED_COMPOUNDS)
docker/docker-compose.community.yml (1)
366-373
: Ensure Consistency and Secure Management of New Environment VariablesThe addition of PostgreSQL and Redis environment variables for the usage service (i.e.,
POSTGRES_HOST
,POSTGRES_PORT
,POSTGRES_DB
,POSTGRES_USER
,POSTGRES_PASSWORD
,REDIS_HOST
,REDIS_PORT
, andREDIS_PASSWORD
) is aligned with the PR's objectives. These changes are consistent with similar configurations in other services and ensure that the usage service can securely connect to the necessary databases.Please verify that:
- The referenced environment variables (e.g.,
${POSTGRES_DB}
) are defined in the corresponding environment files (e.g.,.env.template
) and are documented in the service's README.- Secrets such as database passwords are managed securely in production (consider using Docker secrets or external secret management tools if needed).
7609567
to
84d8730
Compare
Background
Re-use the new authentication/authorization layer introduced within our graphql API service within the usage service for reporting usage with organization access tokens.
Description
/<target-uuid>
for reporting usage with an organization access tokenChecklist