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

refactor(libraries): type safe local storage json #6455

Merged
merged 13 commits into from
Feb 4, 2025
Merged

Conversation

jasonkuhrt
Copy link
Member

No description provided.

Copy link
Contributor

coderabbitai bot commented Jan 31, 2025

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Resolved a defect in the Laboratory component that caused application crashes under specific local storage conditions.
  • Refactor
    • Upgraded data validation and state persistence using an advanced schema validation library.
    • Improved consistency in handling dates, JSON data, and environment variables.
    • Streamlined internal module exports and error handling for enhanced overall stability.

Walkthrough

This pull request implements the zod library for schema validation across multiple components and utility files in the web application. The primary focus is on enhancing type safety and validation for local storage hooks, JSON data structures, and type definitions. Changes include the introduction of Zod schemas for various state variables and the restructuring of type definitions to improve reliability in data handling. The modifications aim to standardize type validation and ensure consistent behavior throughout the application.

Changes

File Change Summary
packages/web/app/src/lib/date-math.ts Replaced Period type definition with Zod schema, added Zod import.
packages/web/app/src/lib/hooks/use-local-storage-json.ts Refactored useLocalStorageJson to use Zod schema validation, updated function signature and type handling.
packages/web/app/src/lib/kit/index.ts Updated exports to import from index_ instead of re-exporting.
packages/web/app/src/lib/kit/index_.ts Added exports for never, types/headers, helpers, json, and zod-helpers modules.
packages/web/app/src/lib/kit/json.ts Introduced Json namespace with Zod-based type definitions and type guards.
packages/web/app/src/lib/kit/zod-helpers.ts Added ZodHelpers namespace with type validation utility functions.
packages/web/app/src/components/target/explorer/provider.tsx, packages/web/app/src/components/ui/changelog/changelog.tsx, packages/web/app/src/lib/preflight-sandbox/graphiql-plugin.tsx Updated local storage hooks to use Zod schema validation.
packages/web/app/src/lib/preflight-sandbox/shared-types.ts, packages/web/app/src/lib/preflight-sandbox/preflight-script-worker.ts Replaced JSONPrimitive references with Kit.Json.Primitive.
packages/web/app/src/pages/target-laboratory.tsx Updated import statement and type for environmentVariables in substituteVariablesInHeaders function.
packages/web/app/src/lib/kit/never.ts Introduced neverCatch function and updated comments in existing functions.
.changeset/tall-lies-raise.md Fixed a crash in the Laboratory view caused by specific local storage conditions.

Possibly related PRs


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
packages/web/app/src/lib/hooks/use-local-storage-json.ts (3)

5-6: Avoid forced casts for better type safety.

Casting args to any and then to Args<$Schema> may undermine the benefits of strict typing. Consider refactoring your parameter types or using function overloads so you can avoid the dual cast.

-export function useLocalStorageJson<$Schema extends z.ZodType>(...args: ArgsInput<$Schema>) {
-  const [key, schema, manualDefaultValue] = args as any as Args<$Schema>;
+export function useLocalStorageJson<$Schema extends z.ZodType>(...args: Args<$Schema>) {
+  const [key, schema, manualDefaultValue] = args;

14-19: Relying on _def.defaultValue() may be fragile.

Accessing _def is an internal implementation detail of Zod and not part of its stable public API. Consider using standard methods like .default(...) or other official Zod helpers to safely retrieve default values and reduce upgrade risks.


40-44: Check dependency array completeness.

Including only [key] in the useCallback dependency array means that updates to schema or manualDefaultValue won't recreate the setter. If these props can change, consider including them as well.

packages/web/app/src/lib/kit/zod-helpers.ts (1)

1-14: Great helpers, but be mindful of Zod internals.

isDefaultType relies on zodType._def.defaultValue, which is considered private API and can break if Zod changes. Otherwise, createTypeGuard is an elegant solution—using safeParse() ensures robust type checking in a concise manner.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff33aee and 70d40b1.

📒 Files selected for processing (12)
  • packages/web/app/src/components/target/explorer/provider.tsx (3 hunks)
  • packages/web/app/src/components/ui/changelog/changelog.tsx (2 hunks)
  • packages/web/app/src/lib/date-math.ts (1 hunks)
  • packages/web/app/src/lib/hooks/use-local-storage-json.ts (1 hunks)
  • packages/web/app/src/lib/kit/index.ts (1 hunks)
  • packages/web/app/src/lib/kit/json.ts (1 hunks)
  • packages/web/app/src/lib/kit/never.ts (1 hunks)
  • packages/web/app/src/lib/kit/zod-helpers.ts (1 hunks)
  • packages/web/app/src/lib/preflight-sandbox/graphiql-plugin.tsx (2 hunks)
  • packages/web/app/src/lib/preflight-sandbox/json.ts (0 hunks)
  • packages/web/app/src/lib/preflight-sandbox/preflight-script-worker.ts (2 hunks)
  • packages/web/app/src/lib/preflight-sandbox/shared-types.ts (4 hunks)
💤 Files with no reviewable changes (1)
  • packages/web/app/src/lib/preflight-sandbox/json.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/web/app/src/lib/kit/never.ts
🧰 Additional context used
🪛 Biome (1.9.4)
packages/web/app/src/lib/kit/json.ts

[error] 15-15: Do not shadow the global "Object" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

🔇 Additional comments (14)
packages/web/app/src/lib/hooks/use-local-storage-json.ts (3)

2-3: Imports look good.

Nothing unusual to note here—importing z from zod and Kit for internal helpers is straightforward.


21-36: Guard against SSR or unavailable storage.

localStorage may be undefined in SSR or restricted environments. Consider handling the absence of localStorage more gracefully (e.g., returning defaultValue or using a safe fallback) to prevent reference errors.

Would you like a script to check for any SSR usage of this hook to ensure no runtime errors occur?


50-64: Type definitions are well structured.

The conditional logic in ArgsInput and GuardZodJsonSchema is clear and leverages Zod and JSON constraints properly. No issues spotted.

packages/web/app/src/lib/kit/index.ts (1)

7-8: Re-exports look straightforward.

Exporting from ./json and ./zod-helpers under Kit is a neat way to consolidate relevant utilities and maintain a clean public API.

packages/web/app/src/lib/kit/json.ts (2)

4-7: LGTM! Well-structured type definitions for JSON primitives.

The use of Zod for defining and validating JSON primitive types is clean and type-safe. The type guard creation using ZodHelpers is a good practice.


9-13: LGTM! Elegant recursive type definition for JSON values.

The recursive type definition using z.lazy() is a good approach for handling nested JSON structures. The type definition is comprehensive, covering all possible JSON value types.

packages/web/app/src/components/target/explorer/provider.tsx (2)

31-34: LGTM! Explicit type definition improves clarity.

The explicit type annotation for defaultPeriod enhances code readability and type safety.


60-60: LGTM! Type-safe local storage implementation.

Good use of Zod schemas for validating local storage values. The default values ensure type safety even when storage is empty.

Also applies to: 64-64

packages/web/app/src/components/ui/changelog/changelog.tsx (1)

23-30: LGTM! Type-safe storage for changelog state.

Good implementation of Zod schemas for validating local storage values. The default values ensure type safety and prevent runtime errors.

packages/web/app/src/lib/preflight-sandbox/shared-types.ts (1)

50-50: LGTM! Consistent use of type-safe JSON primitives.

Good refactoring to use Kit.Json.Primitive consistently across all interfaces for environment variables. This ensures type safety and validation throughout the application.

Also applies to: 95-95, 151-151, 189-189

packages/web/app/src/lib/date-math.ts (1)

9-12: LGTM! Well-structured Zod schema for Period type.

The schema provides both runtime validation and type safety for the Period object structure.

packages/web/app/src/lib/preflight-sandbox/preflight-script-worker.ts (2)

11-11: LGTM! Type-safe environment variables.

Using Kit.Json.Primitive ensures consistent type definitions for environment variables.


111-111: LGTM! Consistent validation check.

Using Kit.Json.isPrimitive aligns with the type definition and provides reliable runtime validation.

packages/web/app/src/lib/preflight-sandbox/graphiql-plugin.tsx (1)

159-159: LGTM! Type-safe local storage state.

Using z.boolean().default(false) ensures type safety and prevents undefined states for the preflight script toggle.

packages/web/app/src/lib/kit/json.ts Show resolved Hide resolved
Copy link
Contributor

github-actions bot commented Jan 31, 2025

🐋 This PR was built and pushed to the following Docker images:

Targets: build

Platforms: linux/amd64

Image Tag: c090d66b71992ebbf4cc01e9ae2686a218b39829

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": "c090d66b71992ebbf4cc01e9ae2686a218b39829",
          "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": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:dockerfile": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:shared": "6ol9x8fedpo2fepijwx1sbx6m"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    }
  },
  "buildx.build.ref": "builder-c5c4d09d-e353-4570-bc96-7278369937b7/builder-c5c4d09d-e353-4570-bc96-7278369937b70/l68h6avcgtbdjnrkrhcsa0kpf",
  "containerimage.config.digest": "sha256:b5da8830ddf185928a47264b19da3ad86115313aac4683ad491e2b46b02c1ef2",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:0cc5fb5561004ac28851fe51ea6253819e47d811adc26be37b1354ad6fa641f8",
    "size": 2075,
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:0cc5fb5561004ac28851fe51ea6253819e47d811adc26be37b1354ad6fa641f8",
  "image.name": "ghcr.io/graphql-hive/app:c090d66b71992ebbf4cc01e9ae2686a218b39829-amd64,ghcr.io/graphql-hive/app:console_995-amd64"
},
"buildx.build.warnings": [
  {
    "vertex": "sha256:66eab14681a2a0624245aee57312391d02bde7a9414f72372962eaeb3d2c73ff",
    "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:c974437adca3e437c1940659b72f1bea031b6ae64ce9e3b0a75eba0d22ffa13d",
    "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
        }
      }
    ]
  },
  {
    "vertex": "sha256:c974437adca3e437c1940659b72f1bea031b6ae64ce9e3b0a75eba0d22ffa13d",
    "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:66eab14681a2a0624245aee57312391d02bde7a9414f72372962eaeb3d2c73ff",
    "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:66eab14681a2a0624245aee57312391d02bde7a9414f72372962eaeb3d2c73ff",
    "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:66eab14681a2a0624245aee57312391d02bde7a9414f72372962eaeb3d2c73ff",
    "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:66eab14681a2a0624245aee57312391d02bde7a9414f72372962eaeb3d2c73ff",
    "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:66eab14681a2a0624245aee57312391d02bde7a9414f72372962eaeb3d2c73ff",
    "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:c974437adca3e437c1940659b72f1bea031b6ae64ce9e3b0a75eba0d22ffa13d",
    "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:c974437adca3e437c1940659b72f1bea031b6ae64ce9e3b0a75eba0d22ffa13d",
    "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:c974437adca3e437c1940659b72f1bea031b6ae64ce9e3b0a75eba0d22ffa13d",
    "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:66eab14681a2a0624245aee57312391d02bde7a9414f72372962eaeb3d2c73ff",
    "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:66eab14681a2a0624245aee57312391d02bde7a9414f72372962eaeb3d2c73ff",
    "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:c974437adca3e437c1940659b72f1bea031b6ae64ce9e3b0a75eba0d22ffa13d",
    "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
        }
      }
    ]
  }
],
"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": "c090d66b71992ebbf4cc01e9ae2686a218b39829",
          "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": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:dockerfile": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:shared": "6ol9x8fedpo2fepijwx1sbx6m"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    }
  },
  "buildx.build.ref": "builder-c5c4d09d-e353-4570-bc96-7278369937b7/builder-c5c4d09d-e353-4570-bc96-7278369937b70/sgtblmqukskl31r48bbw5u2sy",
  "containerimage.config.digest": "sha256:83b4d3827550773e95daea92b47641cae24682995e425236d6afd06baff056c9",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:5caa9817b48528d534a41d386fd0a2b1a8e7ba3907adc4f892c4a8a9642362be",
    "size": 2075,
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:5caa9817b48528d534a41d386fd0a2b1a8e7ba3907adc4f892c4a8a9642362be",
  "image.name": "ghcr.io/graphql-hive/composition-federation-2:c090d66b71992ebbf4cc01e9ae2686a218b39829-amd64,ghcr.io/graphql-hive/composition-federation-2:console_995-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": "c090d66b71992ebbf4cc01e9ae2686a218b39829",
          "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": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:dockerfile": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:shared": "6ol9x8fedpo2fepijwx1sbx6m"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    }
  },
  "buildx.build.ref": "builder-c5c4d09d-e353-4570-bc96-7278369937b7/builder-c5c4d09d-e353-4570-bc96-7278369937b70/gm4hlqs19nt1xkiic1xdjcjep",
  "containerimage.config.digest": "sha256:0a92f93877c28d805505d29b8e2b268a5128154e5a81c662b30e419c8f14f6e4",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:1d90f6439d854a41040d36c8b292e9320d9140b72d220ca08fbda193acf6bf9c",
    "size": 2075,
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:1d90f6439d854a41040d36c8b292e9320d9140b72d220ca08fbda193acf6bf9c",
  "image.name": "ghcr.io/graphql-hive/emails:c090d66b71992ebbf4cc01e9ae2686a218b39829-amd64,ghcr.io/graphql-hive/emails:console_995-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": "c090d66b71992ebbf4cc01e9ae2686a218b39829",
          "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": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:dockerfile": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:shared": "6ol9x8fedpo2fepijwx1sbx6m"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    }
  },
  "buildx.build.ref": "builder-c5c4d09d-e353-4570-bc96-7278369937b7/builder-c5c4d09d-e353-4570-bc96-7278369937b70/n316k3s60i668z0wnajuk4x5w",
  "containerimage.config.digest": "sha256:40b6e57c6f6d5d463e5251ca692bbfeeafc505ebf3841458cc170c086b2cb47b",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:5f14093025eb84b021f5ef228d6106f5cfca39bbe6b0f1ccfb788174c412a88c",
    "size": 2075,
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:5f14093025eb84b021f5ef228d6106f5cfca39bbe6b0f1ccfb788174c412a88c",
  "image.name": "ghcr.io/graphql-hive/policy:c090d66b71992ebbf4cc01e9ae2686a218b39829-amd64,ghcr.io/graphql-hive/policy:console_995-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": "c090d66b71992ebbf4cc01e9ae2686a218b39829",
          "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": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:dockerfile": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:shared": "6ol9x8fedpo2fepijwx1sbx6m"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    }
  },
  "buildx.build.ref": "builder-c5c4d09d-e353-4570-bc96-7278369937b7/builder-c5c4d09d-e353-4570-bc96-7278369937b70/w7covdgutsycg3ij7ekf4efgf",
  "containerimage.config.digest": "sha256:c34d4c33d32f93a54e2ca1908bb4b6f13e77d0fe8c76b037e9f1f098c42dde8b",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:5f19420ba506c0247356a2770c69d7ba9767a36fe8c206b3edde071525882686",
    "size": 2075,
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:5f19420ba506c0247356a2770c69d7ba9767a36fe8c206b3edde071525882686",
  "image.name": "ghcr.io/graphql-hive/rate-limit:c090d66b71992ebbf4cc01e9ae2686a218b39829-amd64,ghcr.io/graphql-hive/rate-limit:console_995-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": "c090d66b71992ebbf4cc01e9ae2686a218b39829",
          "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": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:dockerfile": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:shared": "6ol9x8fedpo2fepijwx1sbx6m"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    }
  },
  "buildx.build.ref": "builder-c5c4d09d-e353-4570-bc96-7278369937b7/builder-c5c4d09d-e353-4570-bc96-7278369937b70/k9m2z7pb08lv3cd0nhy6ufrjx",
  "containerimage.config.digest": "sha256:c231843be8fa05844bdf2c1c6dcd103c96243cc83585f78b44e948dfbfa5abc5",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:f6a235006dae1f2a49f23a8961de45ba2a2827f0a08970dabe486d754564741b",
    "size": 2075,
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:f6a235006dae1f2a49f23a8961de45ba2a2827f0a08970dabe486d754564741b",
  "image.name": "ghcr.io/graphql-hive/schema:c090d66b71992ebbf4cc01e9ae2686a218b39829-amd64,ghcr.io/graphql-hive/schema:console_995-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": "c090d66b71992ebbf4cc01e9ae2686a218b39829",
          "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": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:dockerfile": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:shared": "6ol9x8fedpo2fepijwx1sbx6m"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    }
  },
  "buildx.build.ref": "builder-c5c4d09d-e353-4570-bc96-7278369937b7/builder-c5c4d09d-e353-4570-bc96-7278369937b70/nw8mxxoyl9077wofkcdtetalj",
  "containerimage.config.digest": "sha256:b5ca28d1ba9042343255f0d1eb5d7011c036afeddbb69ef4b6b9fccee4d663f2",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:0a7801453638128ffec150da1e19e94b84e70b5c547c6c58326175fea076e830",
    "size": 2076,
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:0a7801453638128ffec150da1e19e94b84e70b5c547c6c58326175fea076e830",
  "image.name": "ghcr.io/graphql-hive/server:c090d66b71992ebbf4cc01e9ae2686a218b39829-amd64,ghcr.io/graphql-hive/server:console_995-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": "c090d66b71992ebbf4cc01e9ae2686a218b39829",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:dockerfile": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:shared": "6ol9x8fedpo2fepijwx1sbx6m"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    }
  },
  "buildx.build.ref": "builder-c5c4d09d-e353-4570-bc96-7278369937b7/builder-c5c4d09d-e353-4570-bc96-7278369937b70/kz3r1yppthh81oiee7i8chvfq",
  "containerimage.config.digest": "sha256:de31cbcedcd650b4112a1c61add04b093270331bdfa7ae6118c8d3288946e391",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:1e96d1d3a79fdba1793ea1cabdceefb48b2679f4c9769db6bcd3efcf828d5586",
    "size": 2075,
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:1e96d1d3a79fdba1793ea1cabdceefb48b2679f4c9769db6bcd3efcf828d5586",
  "image.name": "ghcr.io/graphql-hive/storage:c090d66b71992ebbf4cc01e9ae2686a218b39829-amd64,ghcr.io/graphql-hive/storage:console_995-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": "c090d66b71992ebbf4cc01e9ae2686a218b39829",
          "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": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:dockerfile": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:shared": "6ol9x8fedpo2fepijwx1sbx6m"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    }
  },
  "buildx.build.ref": "builder-c5c4d09d-e353-4570-bc96-7278369937b7/builder-c5c4d09d-e353-4570-bc96-7278369937b70/mnbg5samqxloqne4mbsy7506i",
  "containerimage.config.digest": "sha256:3f654fe233766e7008653c15725ae18e7a5cfa922a25e846374a190fef2219f8",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:3fc8f99a6b184b92fc1170e641f1e816638bd3886835ec148d2dd443e375a6e3",
    "size": 2075,
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:3fc8f99a6b184b92fc1170e641f1e816638bd3886835ec148d2dd443e375a6e3",
  "image.name": "ghcr.io/graphql-hive/stripe-billing:c090d66b71992ebbf4cc01e9ae2686a218b39829-amd64,ghcr.io/graphql-hive/stripe-billing:console_995-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": "c090d66b71992ebbf4cc01e9ae2686a218b39829",
          "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": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:dockerfile": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:shared": "6ol9x8fedpo2fepijwx1sbx6m"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    }
  },
  "buildx.build.ref": "builder-c5c4d09d-e353-4570-bc96-7278369937b7/builder-c5c4d09d-e353-4570-bc96-7278369937b70/sjobjsjjcpkb4qr2w72wf62f9",
  "containerimage.config.digest": "sha256:b7cfe625b66cc2a0c4d8064b433bd601f16b69896b1cc37bfa3e7ee5e6e4d3e5",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:29e9d38a733c3a7eee6d711f677cf28c6495c4471374f7bd93ed336678da8d5a",
    "size": 2075,
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:29e9d38a733c3a7eee6d711f677cf28c6495c4471374f7bd93ed336678da8d5a",
  "image.name": "ghcr.io/graphql-hive/tokens:c090d66b71992ebbf4cc01e9ae2686a218b39829-amd64,ghcr.io/graphql-hive/tokens:console_995-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": "c090d66b71992ebbf4cc01e9ae2686a218b39829",
          "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": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:dockerfile": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:shared": "6ol9x8fedpo2fepijwx1sbx6m"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    }
  },
  "buildx.build.ref": "builder-c5c4d09d-e353-4570-bc96-7278369937b7/builder-c5c4d09d-e353-4570-bc96-7278369937b70/f2gthgn42b7xbkou6x55rw9u2",
  "containerimage.config.digest": "sha256:40c85d1767ed051621972ea6fcd352b6ae7435cc6b8c9eec10d6484b8f8d70e5",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:77205e826d2d359d1181595bbff6e27ec0e5cb1b51a29fa9d96b20cd346401fe",
    "size": 2075,
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:77205e826d2d359d1181595bbff6e27ec0e5cb1b51a29fa9d96b20cd346401fe",
  "image.name": "ghcr.io/graphql-hive/usage:c090d66b71992ebbf4cc01e9ae2686a218b39829-amd64,ghcr.io/graphql-hive/usage:console_995-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": "c090d66b71992ebbf4cc01e9ae2686a218b39829",
          "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": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:dockerfile": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:shared": "6ol9x8fedpo2fepijwx1sbx6m"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    }
  },
  "buildx.build.ref": "builder-c5c4d09d-e353-4570-bc96-7278369937b7/builder-c5c4d09d-e353-4570-bc96-7278369937b70/cri0cr6eqr5top3ifmmna1y3j",
  "containerimage.config.digest": "sha256:17f37c2a1aedb0d6f5b3f2e55d8c1fa9a68248eeb349ab476f139bbff40f23ff",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:321cb5ba1ac7d236385e02cf09ef5e1914b34763b842cd832d544a9ceeb12a9b",
    "size": 2075,
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:321cb5ba1ac7d236385e02cf09ef5e1914b34763b842cd832d544a9ceeb12a9b",
  "image.name": "ghcr.io/graphql-hive/usage-estimator:c090d66b71992ebbf4cc01e9ae2686a218b39829-amd64,ghcr.io/graphql-hive/usage-estimator:console_995-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": "c090d66b71992ebbf4cc01e9ae2686a218b39829",
          "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": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:dockerfile": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:shared": "6ol9x8fedpo2fepijwx1sbx6m"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    }
  },
  "buildx.build.ref": "builder-c5c4d09d-e353-4570-bc96-7278369937b7/builder-c5c4d09d-e353-4570-bc96-7278369937b70/x9k9kfg8ixfbt003t00bxu5in",
  "containerimage.config.digest": "sha256:28e5919b93510b50531e493f51bee9a72a6f610f76c0fdde0999bfd3c42a7cda",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:a1b47e3b37478995e9cc49012bd59e727275aa9caf9037e63a90068c7e77dbf6",
    "size": 2075,
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:a1b47e3b37478995e9cc49012bd59e727275aa9caf9037e63a90068c7e77dbf6",
  "image.name": "ghcr.io/graphql-hive/usage-ingestor:c090d66b71992ebbf4cc01e9ae2686a218b39829-amd64,ghcr.io/graphql-hive/usage-ingestor:console_995-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": "c090d66b71992ebbf4cc01e9ae2686a218b39829",
          "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": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:dockerfile": "6ol9x8fedpo2fepijwx1sbx6m",
          "local-sessionid:shared": "6ol9x8fedpo2fepijwx1sbx6m"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    }
  },
  "buildx.build.ref": "builder-c5c4d09d-e353-4570-bc96-7278369937b7/builder-c5c4d09d-e353-4570-bc96-7278369937b70/vype9mn1x2sqa03pr9pt9uaf9",
  "containerimage.config.digest": "sha256:e831b939c80d412f18c305ec37616ec2a5f55bbd8cdacb949691c5d8a2b1848c",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:ca25cacc0b4ffedbc5753ef3c394952f911c5ca929321e06e29cd6680f511607",
    "size": 2075,
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:ca25cacc0b4ffedbc5753ef3c394952f911c5ca929321e06e29cd6680f511607",
  "image.name": "ghcr.io/graphql-hive/webhooks:c090d66b71992ebbf4cc01e9ae2686a218b39829-amd64,ghcr.io/graphql-hive/webhooks:console_995-amd64"
}
}

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
packages/web/app/src/lib/hooks/use-local-storage-json.ts (3)

14-19: Replace runtime error with compile-time type check.

The Kit.never() call suggests a runtime error, but this could be caught at compile time.

-      : Kit.ZodHelpers.isDefaultType(schema)
-        ? (schema._def.defaultValue() as z.infer<$Schema>)
-        : Kit.never();
+      : Kit.ZodHelpers.isDefaultType(schema)
+        ? (schema._def.defaultValue() as z.infer<$Schema>)
+        : never; // TypeScript's `never` type for compile-time error

33-35: Consider implementing the suggested improvements.

The TODO comments highlight important features that could enhance the hook's functionality:

  • Error monitoring for debugging and analytics
  • Configurable error handling strategies

Would you like me to help implement these improvements or create an issue to track them?


37-41: Improve error handling granularity.

The current error handling doesn't distinguish between JSON parsing errors and schema validation errors. This makes debugging more difficult.

   try {
     const parsed = JSON.parse(storedValue);
-    return schema.parse(parsed);
-  } catch (_) {
-    return defaultValue;
+    try {
+      return schema.parse(parsed);
+    } catch (e) {
+      console.debug('Schema validation failed:', e);
+      return defaultValue;
+    }
+  } catch (e) {
+    console.debug('JSON parsing failed:', e);
+    return defaultValue;
   }
packages/web/app/src/pages/target-laboratory.tsx (1)

262-262: LGTM! Type-safe environment variables handling.

The change to Kit.Json.Primitive maintains type safety while aligning with the new type system.

Consider adding JSDoc comments to document the expected format of environment variables, especially the {{keyName}} pattern, to improve maintainability.

+/**
+ * Substitutes environment variables in headers using the {{keyName}} pattern.
+ * @param headers - Record of header key-value pairs
+ * @param environmentVariables - Record of environment variables that can be referenced in headers
+ * @returns Record of headers with environment variables substituted
+ */
 function substituteVariablesInHeaders(
   headers: Record<string, string>,
   environmentVariables: Record<string, Kit.Json.Primitive>,
 ) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 70d40b1 and e93ac88.

📒 Files selected for processing (2)
  • packages/web/app/src/lib/hooks/use-local-storage-json.ts (1 hunks)
  • packages/web/app/src/pages/target-laboratory.tsx (2 hunks)
🔇 Additional comments (4)
packages/web/app/src/lib/hooks/use-local-storage-json.ts (2)

44-49: LGTM!

The setter function is well-implemented with proper typing and memoization.


55-69: Well-designed type system!

The type definitions are excellent, featuring:

  • Conditional types for handling schemas with/without defaults
  • JSON value type validation
  • Clear error messages in type constraints
packages/web/app/src/pages/target-laboratory.tsx (2)

62-62: LGTM! Import of Kit module for type-safe JSON handling.

The change aligns with the PR objective of improving type safety for JSON handling.


262-262: Verify type compatibility with preflight script.

Let's ensure the new Kit.Json.Primitive type is compatible with all preflight script implementations.

✅ Verification successful

Type compatibility verified across preflight implementations

The Kit.Json.Primitive type is consistently used for environment variables throughout the codebase, with proper runtime validation in the preflight script worker. No compatibility issues found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other uses of environment variables in preflight scripts
ast-grep --pattern 'environmentVariables: Record<string, $_>'

# Search for any remaining uses of JSONPrimitive
rg 'JSONPrimitive'

Length of output: 82


Script:

#!/bin/bash
# Search for Kit.Json type definitions and usages
rg -A 5 "Kit\.Json"

# Search for environment variables with broader pattern
rg -A 5 "environmentVariables.*Record"

# Search for any type definitions related to environment variables
ast-grep --pattern 'type $_ = { environmentVariables: $_ }'

Length of output: 7720

const [value, setValue] = useState<T>(() => {
const json = localStorage.getItem(key);
export function useLocalStorageJson<$Schema extends z.ZodType>(...args: ArgsInput<$Schema>) {
const [key, schema, manualDefaultValue] = args as any as Args<$Schema>;
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove unsafe type casting.

The use of as any bypasses TypeScript's type checking. Consider using type predicates or type guards instead.

-  const [key, schema, manualDefaultValue] = args as any as Args<$Schema>;
+  const [key, schema, manualDefaultValue] = args as Args<$Schema>;

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/web/app/src/lib/hooks/use-local-storage-json.ts (1)

33-40: Consider implementing the suggested TODO improvements.

The current implementation silently falls back to the default value on any error. Consider:

  1. Adding error monitoring/logging for JSON parsing and schema validation failures
  2. Implementing configurable error handling strategies

Here's a potential implementation:

-    try {
-      return schema.parse(JSON.parse(storedValue));
-    } catch (_) {
-      return defaultValue;
-    }
+    try {
+      return schema.parse(JSON.parse(storedValue));
+    } catch (error) {
+      if (error instanceof z.ZodError) {
+        console.warn(`Schema validation failed for key "${key}":`, error.issues);
+      } else if (error instanceof SyntaxError) {
+        console.warn(`JSON parsing failed for key "${key}":`, error.message);
+      }
+      return defaultValue;
+    }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e93ac88 and f07a764.

📒 Files selected for processing (1)
  • packages/web/app/src/lib/hooks/use-local-storage-json.ts (1 hunks)
🔇 Additional comments (4)
packages/web/app/src/lib/hooks/use-local-storage-json.ts (4)

6-6: Remove unsafe type casting.

The use of as any bypasses TypeScript's type checking. Consider using type predicates or type guards instead.


14-19: LGTM! Well-implemented default value resolution.

The implementation is type-safe and handles all edge cases correctly. The use of Kit.never() ensures compile-time safety when no default value is available.


43-49: LGTM! Efficient setter implementation.

The setter function is well-implemented with appropriate memoization and minimal dependencies.


54-68: LGTM! Excellent type safety implementation.

The type definitions provide strong compile-time guarantees:

  • Ensures JSON-safe types through Kit.Json.Value constraint
  • Handles default values correctly through conditional types
  • Provides clear error messages for invalid schemas

@jasonkuhrt
Copy link
Member Author

Actionable comments posted: 0

🧹 Nitpick comments (1)

packages/web/app/src/lib/hooks/use-local-storage-json.ts (1)> 33-40: Consider implementing the suggested TODO improvements.

The current implementation silently falls back to the default value on any error. Consider:

  1. Adding error monitoring/logging for JSON parsing and schema validation failures
  2. Implementing configurable error handling strategies

Here's a potential implementation:

-    try {
-      return schema.parse(JSON.parse(storedValue));
-    } catch (_) {
-      return defaultValue;
-    }
+    try {
+      return schema.parse(JSON.parse(storedValue));
+    } catch (error) {
+      if (error instanceof z.ZodError) {
+        console.warn(`Schema validation failed for key "${key}":`, error.issues);
+      } else if (error instanceof SyntaxError) {
+        console.warn(`JSON parsing failed for key "${key}":`, error.message);
+      }
+      return defaultValue;
+    }

📜 Review details

This is nice touch, I'll do it. CC @dotansimha - another data point, this time positive

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
packages/web/app/src/lib/hooks/use-local-storage-json.ts (1)

5-6: ⚠️ Potential issue

Remove unsafe type casting.

The use of as any bypasses TypeScript's type checking. Consider using type predicates or type guards instead.

-  const [key, schema, manualDefaultValue] = args as any as Args<$Schema>;
+  const [key, schema, manualDefaultValue] = args as Args<$Schema>;
🧹 Nitpick comments (1)
packages/web/app/src/lib/hooks/use-local-storage-json.ts (1)

33-45: Great error handling improvements!

The error handling now properly distinguishes between JSON parsing and schema validation errors, with appropriate logging. The use of neverCatch for unexpected errors is a good practice.

Consider implementing the suggested improvements from the TODO comments:

  • Add error monitoring
  • Allow configurable error strategies

Would you like me to help implement these improvements?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f07a764 and a3493be.

📒 Files selected for processing (2)
  • packages/web/app/src/lib/hooks/use-local-storage-json.ts (1 hunks)
  • packages/web/app/src/lib/kit/never.ts (1 hunks)
🔇 Additional comments (4)
packages/web/app/src/lib/kit/never.ts (2)

1-7: LGTM! Well-documented error handling utility.

The neverCatch function is a good addition for handling impossible catch cases with proper type safety.


11-11: LGTM! Consistent terminology update.

The documentation update from "bug" to "defect" is consistent with modern terminology.

Also applies to: 19-19

packages/web/app/src/lib/hooks/use-local-storage-json.ts (2)

51-55: LGTM! Type-safe setter implementation.

The set callback correctly uses type inference from the schema and has appropriate dependencies.


61-75: LGTM! Well-designed type definitions.

The type system effectively enforces:

  • JSON-safe schemas
  • Proper handling of default values
  • Clear error messages for invalid schemas

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/web/app/src/lib/hooks/use-local-storage-json.ts (1)

33-46: Implement suggested error handling improvements.

The TODO comments suggest valuable improvements:

  1. Monitoring JSON/schema parse failures
  2. Configurable error strategies

Would you like me to help implement these improvements? I can provide a solution that includes:

  • Error monitoring integration
  • Configurable error strategies ('return' / 'default' / 'throw')
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a3493be and 0017cf1.

📒 Files selected for processing (3)
  • packages/web/app/src/lib/hooks/use-local-storage-json.ts (1 hunks)
  • packages/web/app/src/lib/kit/json.ts (1 hunks)
  • packages/web/app/src/lib/kit/zod-helpers.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/web/app/src/lib/kit/zod-helpers.ts
🧰 Additional context used
🪛 Biome (1.9.4)
packages/web/app/src/lib/kit/json.ts

[error] 16-16: Do not shadow the global "Object" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

🔇 Additional comments (7)
packages/web/app/src/lib/kit/json.ts (4)

1-5: LGTM!

The imports and namespace declaration are appropriate for the functionality.


6-8: LGTM!

The Primitive type definition correctly covers all JSON primitive types with proper type inference and validation.


10-14: LGTM!

The Value type definition correctly handles recursive JSON structures using z.lazy().


16-18: Rename Object to avoid shadowing the global Object.

Consider renaming the Object constant to something more specific like JsonObject to avoid confusion with the global Object.

-  export const Object: z.ZodType<Object> = z.record(Value);
-  export type Object = { [key: string]: Value };
-  export const isObject = ZodHelpers.createTypeGuard(Object);
+  export const JsonObject: z.ZodType<JsonObject> = z.record(Value);
+  export type JsonObject = { [key: string]: Value };
+  export const isJsonObject = ZodHelpers.createTypeGuard(JsonObject);
🧰 Tools
🪛 Biome (1.9.4)

[error] 16-16: Do not shadow the global "Object" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

packages/web/app/src/lib/hooks/use-local-storage-json.ts (3)

5-19: Remove unsafe type casting.

The use of as any bypasses TypeScript's type checking. Consider using type predicates or type guards instead.

-  const [key, schema, manualDefaultValue] = args as any as Args<$Schema>;
+  const [key, schema, manualDefaultValue] = args as Args<$Schema>;

50-56: LGTM!

The set function implementation is correct, type-safe, and has appropriate dependencies.


61-75: LGTM!

The type definitions are well-structured with:

  • Proper JSON validation enforcement
  • Clear error messages for invalid schemas

Copy link
Member

yeah, i can also consider to enable the Commit suggestion feature if it helps to make these even easier?

@jasonkuhrt
Copy link
Member Author

enable the Commit suggestion feature if it helps to make these even easier?

@dotansimha yes please! I was looking for just that.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
.changeset/tall-lies-raise.md (2)

1-3: Enhance Changeset Metadata

Ensure that the changeset header includes all necessary details such as a full description of the change, relevant GitHub issue links (if available), and before/after examples where applicable. This additional context can help future maintainers understand the impact and rationale behind the patch.


5-5: Improve Language Clarity in the Description

The current description has some language issues: it is missing an article before "Laboratory", exhibits a tense that may not clearly convey the past problem, and could benefit from improved punctuation. Consider revising the sentence for better clarity and professionalism. For example:

-A minor defect in Laboratory is fixed wherein it would crash when local storage was in a certain state. 
+A minor defect in the Laboratory component has been fixed that previously caused the application to crash when local storage was in a particular state.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~5-~5: You might be missing the article “the” here.
Context: ...-- 'hive': patch --- A minor defect in Laboratory is fixed wherein it would crash when lo...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~5-~5: This verb may not be in the correct tense. Consider changing the tense to fit the context better.
Context: ...patch --- A minor defect in Laboratory is fixed wherein it would crash when local...

(AI_EN_LECTOR_REPLACEMENT_VERB_TENSE)


[uncategorized] ~5-~5: Possible missing comma found.
Context: ...ch --- A minor defect in Laboratory is fixed wherein it would crash when local stora...

(AI_HYDRA_LEO_MISSING_COMMA)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0017cf1 and ecb1af7.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (1)
  • .changeset/tall-lies-raise.md (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
.changeset/tall-lies-raise.md (1)

Pattern .changeset/**: A special folder with the files created/managed by Changesets tool.
In PRs that already includes this file, please make sure that the content of the markdown file includes:

  • Full description of the change
  • A link to the relevant GitHub issues (if any)
  • Example with before/after
  • If the change is of type major, please ensure that the content have content about migration with before/after.
🪛 LanguageTool
.changeset/tall-lies-raise.md

[uncategorized] ~5-~5: You might be missing the article “the” here.
Context: ...-- 'hive': patch --- A minor defect in Laboratory is fixed wherein it would crash when lo...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~5-~5: This verb may not be in the correct tense. Consider changing the tense to fit the context better.
Context: ...patch --- A minor defect in Laboratory is fixed wherein it would crash when local...

(AI_EN_LECTOR_REPLACEMENT_VERB_TENSE)


[uncategorized] ~5-~5: Possible missing comma found.
Context: ...ch --- A minor defect in Laboratory is fixed wherein it would crash when local stora...

(AI_HYDRA_LEO_MISSING_COMMA)

Copy link
Contributor

github-actions bot commented Feb 3, 2025

🚀 Snapshot Release (alpha)

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

Package Version Info
hive 5.0.1-alpha-20250204034559-c090d66b71992ebbf4cc01e9ae2686a218b39829 npm ↗︎ unpkg ↗︎

@jasonkuhrt
Copy link
Member Author

Something up with Storybook, after fixing that, merging.

Copy link
Contributor

github-actions bot commented Feb 4, 2025

📚 Storybook Deployment

The latest changes are available as preview in: https://b9033331.hive-storybook.pages.dev

Copy link
Member Author

Choose a reason for hiding this comment

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

@n1ru4l I introduced this file because Storybook doesn't seem to support re-export namespace syntax and I didn't want to lose the Kit namespace. I think the reason its building on trunk is that until this PR Kit code wasn't being pulled into any source code that Storybook was analyzing.

CleanShot 2025-02-03 at 22 37 42@2x

I also tried this but TS rejects it:

import * as _ from './index';

export { _ as Kit };
Circular definition of import alias '_'.ts(2303)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/web/app/src/lib/kit/index.ts (1)

1-10: Well-documented workaround for Storybook's Babel limitation!

The comments clearly explain the technical constraint and the chosen solution. Consider adding a TODO comment with a ticket to track the potential removal of this workaround once Storybook's Babel version is upgraded.

 // Storybook (or the version we are using)
 // is using a version of Babel that does not
 // support re-exporting as namespaces:
 //
 // export * as Kit from './index';
 //
 // So we have to re-export everything manually
 // and incur an additional index_ file for it
 // too:
+// TODO: Remove this workaround once Storybook's Babel version supports namespace re-exports
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f3a7a1 and c090d66.

📒 Files selected for processing (2)
  • .changeset/tall-lies-raise.md (1 hunks)
  • packages/web/app/src/lib/kit/index.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .changeset/tall-lies-raise.md
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: alpha / npm / snapshot
  • GitHub Check: typescript / typecheck
  • GitHub Check: static-analysis / analyze (typescript)
  • GitHub Check: storybook-preview / deployment
  • GitHub Check: static-analysis / analyze (javascript)
  • GitHub Check: build / dockerize (linux/arm64)
  • GitHub Check: build / dockerize (linux/amd64)
  • GitHub Check: alpha / cli-artifacts
  • GitHub Check: code-style / eslint-and-prettier
🔇 Additional comments (1)
packages/web/app/src/lib/kit/index.ts (1)

11-14: LGTM! Verify the impact on dependent modules.

The implementation correctly maintains the same external API while working around the Babel limitation.

Let's verify that this change doesn't break any imports in the codebase:

✅ Verification successful

Impact Verified: Dependent modules import Kit as expected.

The search results show that all files continue to import Kit from the same module path (../kit or its alias equivalent), and there are no dynamic imports that could be affected. This confirms that the API remains stable and the change does not break any dependent modules.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all imports of Kit are compatible with the new structure

# Search for Kit imports
echo "Checking Kit imports..."
rg -A 2 "import.*Kit.*from.*['\"].*kit['\"]"

# Search for potential dynamic imports
echo "Checking dynamic imports..."
rg "import\(.*kit.*\)"

Length of output: 2005

@jasonkuhrt jasonkuhrt merged commit 6924a1a into main Feb 4, 2025
29 checks passed
@jasonkuhrt jasonkuhrt deleted the console-995 branch February 4, 2025 04:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants