diff --git a/docs/docs.json b/docs/docs.json
index ff281e47..5729ba69 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -249,6 +249,16 @@
"studio/schema-explorer",
"studio/schema-registry",
"studio/schema-checks",
+ {
+ "group": "Check Extensions",
+ "icon": "puzzle-piece-simple",
+ "pages": [
+ "studio/subgraph-check-extensions",
+ "studio/sce/payload-structure",
+ "studio/sce/response-structure",
+ "studio/sce/file-content"
+ ]
+ },
"studio/schema-contracts",
"studio/overrides",
"studio/changelog",
diff --git a/docs/images/studio/sce/config.png b/docs/images/studio/sce/config.png
new file mode 100644
index 00000000..8a31ccac
Binary files /dev/null and b/docs/images/studio/sce/config.png differ
diff --git a/docs/studio/sce/file-content.mdx b/docs/studio/sce/file-content.mdx
new file mode 100644
index 00000000..e1a294f2
--- /dev/null
+++ b/docs/studio/sce/file-content.mdx
@@ -0,0 +1,49 @@
+---
+title: "Structure of "
+sidebarTitle: Overview
+icon: puzzle-piece-simple
+description: "Validate schema changes before deploying them to production on your own premises."
+---
+
+```typescript
+enum LintSeverity {
+ Warning = 0,
+ Error = 1
+}
+
+interface LintIssue {
+ lintRuleType: string;
+ severity: LintSeverity;
+ message: string;
+ issueLocation: {
+ line: number;
+ column: number;
+ endLine?: number;
+ endColumn?: number;
+ };
+}
+
+enum GraphPruningSeverity {
+ Warning = 0,
+ Error = 1
+}
+
+interface GraphPruningIssue {
+ graphPruningRuleType: string;
+ severity: GraphPruningSeverity;
+ fieldPath: string;
+ message: string;
+ issueLocation: {
+ line: number;
+ column: number;
+ endLine?: number;
+ endColumn?: number;
+ };
+ federatedGraphId: string;
+ federatedGraphName: string;
+ subgraphName?: string;
+}
+
+interface SubgraphCheckExtensionContent {
+}
+```
\ No newline at end of file
diff --git a/docs/studio/sce/payload-structure.mdx b/docs/studio/sce/payload-structure.mdx
new file mode 100644
index 00000000..4b78f312
--- /dev/null
+++ b/docs/studio/sce/payload-structure.mdx
@@ -0,0 +1,91 @@
+---
+title: "Structure of "
+sidebarTitle: Overview
+icon: puzzle-piece-simple
+description: "Validate schema changes before deploying them to production on your own premises."
+---
+
+## SubgraphCheckExtensionPayload
+| Field | Description |
+|----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|
+| actorId | The unique identifier of the actor that triggered the check. |
+| checkId | The unique identifier of the check. |
+| organization | Information about the organization that triggered the check. |
+| namespace | Information about the associated namespace. |
+| vcsContext | Details about the Version Control System (VCS) that triggered the check. This field is only included when the check is initiated from a VCS. |
+| affectedGraphs | A list of all graphs affected by the check. |
+| subgraph | The subgraph that triggered the check. This field is only included when the check is for an existing subgraph. |
+| url | The URL from which the file containing bulk data can be downloaded. |
+
+### OrganizationContext
+| Field | Description |
+|-------|--------------------------------------------|
+| id | The unique identifier of the organization. |
+| slug | The slug of the organization. |
+
+### NamespaceContext
+| Field | Description |
+|-------|-----------------------------------------|
+| id | The unique identifier of the namespace. |
+| name | The display name of the namespace. |
+
+### VCSContext
+| Field | Description |
+|-----------|------------------------------------------------------|
+| author | The email address of the commit author. |
+| commitSha | The SHA hash of the commit that triggered the check. |
+| branch | The name of the branch associated with the commit. |
+
+### AffectedGraphInfo
+| Field | Description |
+|-------|-------------------------------------|
+| id | The unique identifier of the graph. |
+| name | The name of the graph. |
+
+### SubgraphContext
+| Field | Description |
+|-----------|------------------------------------------------------------------|
+| id | The unique identifier of the subgraph. |
+| name | The name of the subgraph. |
+| isDeleted | Indicates whether the check was triggered by a subgraph deletion. |
+
+## TypeScript definition
+
+```typescript
+interface OrganizationInfo {
+ id: string;
+ slug: string;
+}
+
+interface NamespaceInfo {
+ id: string;
+ name: string;
+}
+
+interface VCSContext {
+ author: string;
+ commitSha: string;
+ branch: string;
+}
+
+interface AffectedGraphInfo {
+ id: string;
+ name: string;
+ namespace: NamespaceInfo;
+}
+
+interface SubgraphInfo {
+ id: string;
+ name: string;
+ isDeleted: boolean;
+}
+
+interface SubgraphCheckExtensionPayload {
+ organization: OrganizationInfo;
+ namespace: NamespaceInfo;
+ vcsContext: VCSContext | undefined;
+ affectedGraphs: AffectedGraphInfo[];
+ url: string;
+ subgraph: SubgraphInfo | undefined;
+}
+```
\ No newline at end of file
diff --git a/docs/studio/sce/response-structure.mdx b/docs/studio/sce/response-structure.mdx
new file mode 100644
index 00000000..fbdb7839
--- /dev/null
+++ b/docs/studio/sce/response-structure.mdx
@@ -0,0 +1,27 @@
+```typescript
+enum LintSeverity {
+ Warning = 0,
+ Error = 1
+}
+
+interface LintIssue {
+ lintRuleType: string;
+ severity: LintSeverity;
+ message: string;
+ issueLocation: {
+ line: number;
+ column: number;
+ endLine?: number;
+ endColumn?: number;
+ };
+}
+
+interface Overwrite {
+ lintIssues: LintIssue[];
+}
+
+interface SubgraphCheckExtensionReply {
+ errorMessage: string | undefined;
+ overwrite: Overwrite | undefined;
+}
+```
\ No newline at end of file
diff --git a/docs/studio/subgraph-check-extensions.mdx b/docs/studio/subgraph-check-extensions.mdx
new file mode 100644
index 00000000..54522a24
--- /dev/null
+++ b/docs/studio/subgraph-check-extensions.mdx
@@ -0,0 +1,228 @@
+---
+title: "Subgraph Check Extensions"
+sidebarTitle: Overview
+icon: puzzle-piece-simple
+description: "Validate schema changes before deploying them to production on your own premises."
+---
+
+A subgraph check extension allows you to validate if a proposed schema change will produce any error before shipping
+it to production with your own validator.
+
+## How it works
+When you have enabled the subgraph check extension for a namespace, everytime a check is performed against a graph that
+belongs to said namespace, we send a request to the [configured](#configuration) endpoint with information about the
+and allow you to overwrite the `lint issues` or return an error which would fail
+
+## Configuration
+
+
+
+
+
+| Option | Description |
+|-------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Endpoint | The URL to which each request is sent. This endpoint must be accessible from Cosmo. |
+| Secret Key | A value used to generate the request signature when sending data to the configured endpoint. This signature helps [verify](#verification) that the request originates from Cosmo and has not been altered. |
+| Include Composed SDL | When enabled, both the previous and current SDL (Schema Definition Language) versions are sent to your service. |
+| Include Lint Warnings and Errors | When enabled, all detected lint issues are sent to your service. These issues are evaluated using the [Linter Rules](/studio/lint-policy/linter-rules). |
+| Include Graph Pruning Warnings and Errors | When enabled, all detected graph pruning issues are sent to your service. For more information, see [Graph Pruning](/studio/graph-pruning). |
+| Include Schema Changes | When enabled, details of schema changes are included in the data sent to your service. |
+| Include Affected Operations | When enabled, information about affected operations is included in the data sent to your service. | |
+
+## Verification
+To ensure the payload data is coming from a trusted source and hasn’t been tampered with during transit, we employ HMAC
+signatures. When setting up the *Subgraph Check Extension* for a namespace, you can provide a secret key. This
+secret key is used to compute a signature that is sent along with each request.
+
+The header containing this signature is `X-Cosmo-Signature-256`.
+
+### Verification Example
+To verify the request, you need to compute the HMAC signature on your server and compare it to the signature in the
+`X-Cosmo-Signature-256` header.
+
+Here’s an example in Node.js:
+```typescript
+import crypto from 'crypto';
+
+function verifySignature(body, receivedSignature, secret) {
+ const computedSignature = crypto
+ .createHmac('sha256', secret)
+ .update(body)
+ .digest('hex');
+
+ return computedSignature === receivedSignature;
+}
+
+// Usage:
+const isVerified = verifySignature(JSON.stringify(req.body), req.headers['x-cosmo-signature-256'], YOUR_SECRET);
+```
+
+## Handler Example
+For this example we are using `fastify` and `tsx` to run the local server on port `4000`. Before running any check,
+we need to configure the check extension to point to our local server and set the secret key. For this example, we are
+using the following values:
+
+- Endpoint: `http://localhost:4000/check-schema`
+- Secret key: `...`
+
+
+ ```typescript server.ts
+ import Fastify, { type FastifyInstance } from 'fastify'
+
+ import { SubgraphCheckExtensionPayload, SubgraphCheckExtensionReply } from './types'
+ import { verifySignature } from './utils'
+
+ const YOUR_SECRET = '...'
+ const server: FastifyInstance = Fastify({ logger: true })
+
+ server.post<{
+ Body: SubgraphCheckExtensionPayload,
+ Reply: SubgraphCheckExtensionReply
+ }>(
+ '/check-schema',
+ {
+ config: { rawBody: true }
+ },
+ async (req, res) => {
+ if (!req.body) {
+ res.code(400)
+ return { errorMessage: 'Bad request' }
+ }
+
+ const { body } = req
+ const cosmoSignature = req.headers['x-cosmo-signature-256']
+ if (!verifySignature(body, cosmoSignature, YOUR_SECRET)) {
+ res.code(400)
+ return { errorMessage: 'Bad request' }
+ }
+
+ // We can run checks conditionally
+ if (body.namespace.name !== 'default' || body.subgraph?.name !== 'family') {
+ // We only want to overwrite the lint issues for the subgraph `family` on the namespace `default`
+ res.code(204)
+ return
+ }
+
+ return {
+ overwrite: {
+ lintIssues: [
+ {
+ lintRuleType: 'TYPE_SUFFIX',
+ severity: 1,
+ message: 'Type names should use the prefix `Type`',
+ issueLocation: {
+ line: 9,
+ column: 6,
+ endLine: 9,
+ endColumn: 11,
+ },
+ },
+ ],
+ },
+ }
+ })
+
+ const start = async () => {
+ try {
+ await server.listen({ port: 4000 })
+
+ const address = server.server.address()
+ const port = typeof address === 'string' ? address : address?.port
+ } catch (err) {
+ server.log.error(err)
+ process.exit(1)
+ }
+ }
+
+ start()
+ ```
+
+ ```typescript utils.ts
+ import crypto from 'node:crypto';
+
+ export function verifySignature(body: unknown, receivedSignature: string, secret: string) {
+ const computedSignature = crypto
+ .createHmac('sha256', secret)
+ .update(JSON.stringify(body))
+ .digest('hex');
+
+ return computedSignature === receivedSignature;
+ }
+ ```
+
+ ```typescript types.ts
+ export interface OrganizationContext {
+ id: string;
+ slug: string;
+ }
+
+ export interface NamespaceContext {
+ id: string;
+ name: string;
+ }
+
+ export interface VCSContext {
+ author: string;
+ commitSha: string;
+ branch: string;
+ }
+
+ export interface AffectedGraphItem {
+ id: string;
+ name: string;
+ }
+
+ export interface SubgraphContext {
+ id: string;
+ name: string;
+ isDeleted: boolean;
+ }
+
+ export interface SubgraphCheckExtensionPayload {
+ actorId: string;
+ checkId: string;
+ organization: OrganizationContext;
+ namespace: NamespaceContext;
+ vcsContext?: VCSContext;
+ affectedGraphs: AffectedGraphItem[];
+ url: string;
+ subgraph?: SubgraphContext;
+ }
+
+ enum LintSeverity {
+ Warning = 0,
+ Error = 1
+ }
+
+ export interface LintIssue {
+ lintRuleType: string;
+ severity: LintSeverity;
+ message: string;
+ issueLocation: {
+ line: number;
+ column: number;
+ endLine?: number;
+ endColumn?: number;
+ };
+ }
+
+ export interface OverwriteInfo {
+ lintIssues: LintIssue[];
+ }
+
+ export interface SubgraphCheckExtensionReply {
+ errorMessage?: string;
+ overwrite?: OverwriteInfo;
+ }
+ ```
+
+ ```json package.json
+ {
+ ...
+ "scripts": {
+ "dev": "tsx watch server.ts"
+ }
+ ...
+ }
+ ```
+
\ No newline at end of file