diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts
index 70ba7e87b..58931628e 100644
--- a/backend/src/lib/api-docs/constants.ts
+++ b/backend/src/lib/api-docs/constants.ts
@@ -479,3 +479,74 @@ export const PROJECT_USER_ADDITIONAL_PRIVILEGE = {
projectMembershipId: "Project membership id of user"
}
};
+
+export const INTEGRATION_AUTH = {
+ GET: {
+ integrationAuthId: "The id of integration authentication object."
+ },
+ DELETE: {
+ integration: "The slug of the integration to be unauthorized.",
+ projectId: "The ID of the project to delete the integration auth from."
+ },
+ DELETE_BY_ID: {
+ integrationAuthId: "The id of integration authentication object to delete."
+ },
+ CREATE_ACCESS_TOKEN: {
+ workspaceId: "The ID of the project to create the integration auth for.",
+ integration: "The slug of integration for the auth object.",
+ accessId: "The unique authorized access id of the external integration provider.",
+ accessToken: "The unique authorized access token of the external integration provider.",
+ url: "",
+ namespace: "",
+ refreshToken: "The refresh token for integration authorization."
+ },
+ LIST_AUTHORIZATION: {
+ workspaceId: "The ID of the project to list integration auths for."
+ }
+};
+
+export const INTEGRATION = {
+ CREATE: {
+ integrationAuthId: "The ID of the integration auth object to link with integration.",
+ app: "The name of the external integration providers app entity that you want to sync secrets with. Used in Netlify, GitHub, Vercel integrations.",
+ isActive: "Whether the integration should be active or disabled.",
+ appId:
+ "The ID of the external integration providers app entity that you want to sync secrets with. Used in Netlify, GitHub, Vercel integrations.",
+ secretPath: "The path of the secrets to sync secrets from.",
+ sourceEnvironment: "The environment to sync secret from.",
+ targetEnvironment:
+ "The target environment of the integration provider. Used in cloudflare pages, TeamCity, Gitlab integrations.",
+ targetEnvironmentId:
+ "The target environment id of the integration provider. Used in cloudflare pages, teamcity, gitlab integrations.",
+ targetService:
+ "The service based grouping identifier of the external provider. Used in Terraform cloud, Checkly, Railway and NorthFlank",
+ targetServiceId:
+ "The service based grouping identifier ID of the external provider. Used in Terraform cloud, Checkly, Railway and NorthFlank",
+ owner: "External integration providers service entity owner. Used in Github.",
+ path: "Path to save the synced secrets. Used by Gitlab, AWS Parameter Store, Vault",
+ region: "AWS region to sync secrets to.",
+ scope: "Scope of the provider. Used by Github, Qovery",
+ metadata: {
+ secretPrefix: "The prefix for the saved secret. Used by GCP",
+ secretSuffix: "The suffix for the saved secret. Used by GCP",
+ initialSyncBehavoir: "Type of syncing behavoir with the integration",
+ shouldAutoRedeploy: "Used by Render to trigger auto deploy",
+ secretGCPLabel: "The label for the GCP secrets"
+ }
+ },
+ UPDATE: {
+ integrationId: "The ID of the integration object.",
+ app: "The name of the external integration providers app entity that you want to sync secrets with. Used in Netlify, GitHub, Vercel integrations.",
+ appId:
+ "The ID of the external integration providers app entity that you want to sync secrets with. Used in Netlify, GitHub, Vercel integrations.",
+ isActive: "Whether the integration should be active or disabled.",
+ secretPath: "The path of the secrets to sync secrets from.",
+ owner: "External integration providers service entity owner. Used in Github.",
+ targetEnvironment:
+ "The target environment of the integration provider. Used in cloudflare pages, TeamCity, Gitlab integrations.",
+ environment: "The environment to sync secrets from."
+ },
+ DELETE: {
+ integrationId: "The ID of the integration object."
+ }
+};
diff --git a/backend/src/server/routes/v1/integration-auth-router.ts b/backend/src/server/routes/v1/integration-auth-router.ts
index 004ca298d..a68479074 100644
--- a/backend/src/server/routes/v1/integration-auth-router.ts
+++ b/backend/src/server/routes/v1/integration-auth-router.ts
@@ -1,6 +1,7 @@
import { z } from "zod";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
+import { INTEGRATION_AUTH } from "@app/lib/api-docs";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -10,8 +11,14 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
server.route({
url: "/integration-options",
method: "GET",
- onRequest: verifyAuth([AuthMode.JWT]),
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
+ description: "List of integrations available.",
+ security: [
+ {
+ bearerAuth: []
+ }
+ ],
response: {
200: z.object({
integrationOptions: z
@@ -38,10 +45,16 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
server.route({
url: "/:integrationAuthId",
method: "GET",
- onRequest: verifyAuth([AuthMode.JWT]),
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
+ description: "Get details of an integration authorization by auth object id.",
+ security: [
+ {
+ bearerAuth: []
+ }
+ ],
params: z.object({
- integrationAuthId: z.string().trim()
+ integrationAuthId: z.string().trim().describe(INTEGRATION_AUTH.GET.integrationAuthId)
}),
response: {
200: z.object({
@@ -64,11 +77,17 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
server.route({
url: "/",
method: "DELETE",
- onRequest: verifyAuth([AuthMode.JWT]),
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
+ description: "Remove all integration's auth object from the project.",
+ security: [
+ {
+ bearerAuth: []
+ }
+ ],
querystring: z.object({
- integration: z.string().trim(),
- projectId: z.string().trim()
+ integration: z.string().trim().describe(INTEGRATION_AUTH.DELETE.integration),
+ projectId: z.string().trim().describe(INTEGRATION_AUTH.DELETE.projectId)
}),
response: {
200: z.object({
@@ -104,10 +123,16 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
server.route({
url: "/:integrationAuthId",
method: "DELETE",
- onRequest: verifyAuth([AuthMode.JWT]),
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
+ description: "Remove an integration auth object by object id.",
+ security: [
+ {
+ bearerAuth: []
+ }
+ ],
params: z.object({
- integrationAuthId: z.string().trim()
+ integrationAuthId: z.string().trim().describe(INTEGRATION_AUTH.DELETE_BY_ID.integrationAuthId)
}),
response: {
200: z.object({
@@ -183,16 +208,22 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
server.route({
url: "/access-token",
method: "POST",
- onRequest: verifyAuth([AuthMode.JWT]),
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
+ description: "Create the integration authentication object required for syncing secrets.",
+ security: [
+ {
+ bearerAuth: []
+ }
+ ],
body: z.object({
- workspaceId: z.string().trim(),
- integration: z.string().trim(),
- accessId: z.string().trim().optional(),
- accessToken: z.string().trim().optional(),
- url: z.string().url().trim().optional(),
- namespace: z.string().trim().optional(),
- refreshToken: z.string().trim().optional()
+ workspaceId: z.string().trim().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.workspaceId),
+ integration: z.string().trim().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.integration),
+ accessId: z.string().trim().optional().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.accessId),
+ accessToken: z.string().trim().optional().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.accessToken),
+ url: z.string().url().trim().optional().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.url),
+ namespace: z.string().trim().optional().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.namespace),
+ refreshToken: z.string().trim().optional().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.refreshToken)
}),
response: {
200: z.object({
diff --git a/backend/src/server/routes/v1/integration-router.ts b/backend/src/server/routes/v1/integration-router.ts
index 4859ca584..0bc434dbe 100644
--- a/backend/src/server/routes/v1/integration-router.ts
+++ b/backend/src/server/routes/v1/integration-router.ts
@@ -2,6 +2,7 @@ import { z } from "zod";
import { IntegrationsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
+import { INTEGRATION } from "@app/lib/api-docs";
import { removeTrailingSlash, shake } from "@app/lib/fn";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -13,33 +14,45 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
url: "/",
method: "POST",
schema: {
+ description: "Create an integration to sync secrets.",
+ security: [
+ {
+ bearerAuth: []
+ }
+ ],
body: z.object({
- integrationAuthId: z.string().trim(),
- app: z.string().trim().optional(),
- isActive: z.boolean(),
- appId: z.string().trim().optional(),
- secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
- sourceEnvironment: z.string().trim(),
- targetEnvironment: z.string().trim().optional(),
- targetEnvironmentId: z.string().trim().optional(),
- targetService: z.string().trim().optional(),
- targetServiceId: z.string().trim().optional(),
- owner: z.string().trim().optional(),
- path: z.string().trim().optional(),
- region: z.string().trim().optional(),
- scope: z.string().trim().optional(),
+ integrationAuthId: z.string().trim().describe(INTEGRATION.CREATE.integrationAuthId),
+ app: z.string().trim().optional().describe(INTEGRATION.CREATE.app),
+ isActive: z.boolean().describe(INTEGRATION.CREATE.isActive).default(true),
+ appId: z.string().trim().optional().describe(INTEGRATION.CREATE.appId),
+ secretPath: z
+ .string()
+ .trim()
+ .default("/")
+ .transform(removeTrailingSlash)
+ .describe(INTEGRATION.CREATE.secretPath),
+ sourceEnvironment: z.string().trim().describe(INTEGRATION.CREATE.sourceEnvironment),
+ targetEnvironment: z.string().trim().optional().describe(INTEGRATION.CREATE.targetEnvironment),
+ targetEnvironmentId: z.string().trim().optional().describe(INTEGRATION.CREATE.targetEnvironmentId),
+ targetService: z.string().trim().optional().describe(INTEGRATION.CREATE.targetService),
+ targetServiceId: z.string().trim().optional().describe(INTEGRATION.CREATE.targetServiceId),
+ owner: z.string().trim().optional().describe(INTEGRATION.CREATE.owner),
+ path: z.string().trim().optional().describe(INTEGRATION.CREATE.path),
+ region: z.string().trim().optional().describe(INTEGRATION.CREATE.region),
+ scope: z.string().trim().optional().describe(INTEGRATION.CREATE.scope),
metadata: z
.object({
- secretPrefix: z.string().optional(),
- secretSuffix: z.string().optional(),
- initialSyncBehavior: z.string().optional(),
- shouldAutoRedeploy: z.boolean().optional(),
+ secretPrefix: z.string().optional().describe(INTEGRATION.CREATE.metadata.secretPrefix),
+ secretSuffix: z.string().optional().describe(INTEGRATION.CREATE.metadata.secretSuffix),
+ initialSyncBehavior: z.string().optional().describe(INTEGRATION.CREATE.metadata.initialSyncBehavoir),
+ shouldAutoRedeploy: z.boolean().optional().describe(INTEGRATION.CREATE.metadata.shouldAutoRedeploy),
secretGCPLabel: z
.object({
labelName: z.string(),
labelValue: z.string()
})
.optional()
+ .describe(INTEGRATION.CREATE.metadata.secretGCPLabel)
})
.optional()
}),
@@ -49,7 +62,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
})
}
},
- onRequest: verifyAuth([AuthMode.JWT]),
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const { integration, integrationAuth } = await server.services.integration.createIntegration({
actorId: req.permission.id,
@@ -102,17 +115,28 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
url: "/:integrationId",
method: "PATCH",
schema: {
+ description: "Update an integration by integration id",
+ security: [
+ {
+ bearerAuth: []
+ }
+ ],
params: z.object({
- integrationId: z.string().trim()
+ integrationId: z.string().trim().describe(INTEGRATION.UPDATE.integrationId)
}),
body: z.object({
- app: z.string().trim(),
- appId: z.string().trim(),
- isActive: z.boolean(),
- secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
- targetEnvironment: z.string().trim(),
- owner: z.string().trim(),
- environment: z.string().trim()
+ app: z.string().trim().describe(INTEGRATION.UPDATE.app),
+ appId: z.string().trim().describe(INTEGRATION.UPDATE.appId),
+ isActive: z.boolean().describe(INTEGRATION.UPDATE.isActive),
+ secretPath: z
+ .string()
+ .trim()
+ .default("/")
+ .transform(removeTrailingSlash)
+ .describe(INTEGRATION.UPDATE.secretPath),
+ targetEnvironment: z.string().trim().describe(INTEGRATION.UPDATE.targetEnvironment),
+ owner: z.string().trim().describe(INTEGRATION.UPDATE.owner),
+ environment: z.string().trim().describe(INTEGRATION.UPDATE.environment)
}),
response: {
200: z.object({
@@ -120,7 +144,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
})
}
},
- onRequest: verifyAuth([AuthMode.JWT]),
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const integration = await server.services.integration.updateIntegration({
actorId: req.permission.id,
@@ -138,8 +162,14 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
url: "/:integrationId",
method: "DELETE",
schema: {
+ description: "Remove an integration using the integration object ID",
+ security: [
+ {
+ bearerAuth: []
+ }
+ ],
params: z.object({
- integrationId: z.string().trim()
+ integrationId: z.string().trim().describe(INTEGRATION.DELETE.integrationId)
}),
response: {
200: z.object({
@@ -147,7 +177,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
})
}
},
- onRequest: verifyAuth([AuthMode.JWT]),
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const integration = await server.services.integration.deleteIntegration({
actorId: req.permission.id,
diff --git a/backend/src/server/routes/v1/project-router.ts b/backend/src/server/routes/v1/project-router.ts
index 55f1fdda9..ca01820a9 100644
--- a/backend/src/server/routes/v1/project-router.ts
+++ b/backend/src/server/routes/v1/project-router.ts
@@ -7,7 +7,7 @@ import {
UserEncryptionKeysSchema,
UsersSchema
} from "@app/db/schemas";
-import { PROJECTS } from "@app/lib/api-docs";
+import { INTEGRATION_AUTH, PROJECTS } from "@app/lib/api-docs";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { ProjectFilterType } from "@app/services/project/project-types";
@@ -332,8 +332,14 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
url: "/:workspaceId/authorizations",
method: "GET",
schema: {
+ description: "List integration auth objects for a workspace.",
+ security: [
+ {
+ bearerAuth: []
+ }
+ ],
params: z.object({
- workspaceId: z.string().trim()
+ workspaceId: z.string().trim().describe(INTEGRATION_AUTH.LIST_AUTHORIZATION.workspaceId)
}),
response: {
200: z.object({
@@ -341,7 +347,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
})
}
},
- onRequest: verifyAuth([AuthMode.JWT]),
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const authorizations = await server.services.integrationAuth.listIntegrationAuthByProjectId({
actorId: req.permission.id,
diff --git a/docs/api-reference/endpoints/integrations/create-auth.mdx b/docs/api-reference/endpoints/integrations/create-auth.mdx
new file mode 100644
index 000000000..5af7a0f9c
--- /dev/null
+++ b/docs/api-reference/endpoints/integrations/create-auth.mdx
@@ -0,0 +1,32 @@
+---
+title: "Create Auth"
+openapi: "POST /api/v1/integration-auth/access-token"
+---
+
+## Integration Authentication Parameters
+
+The integration authentication endpoint is generic and can be used for all native integrations.
+For specific integration parameters for a given service, please review the respective documentation below.
+
+
+
+
+ This value must be **aws-secret-manager**.
+
+
+ Infisical project id for the integration.
+
+
+ The AWS IAM User Access ID.
+
+
+ The AWS IAM User Access Secret Key.
+
+
+
+ Coming Soon
+
+
+ Coming Soon
+
+
diff --git a/docs/api-reference/endpoints/integrations/create.mdx b/docs/api-reference/endpoints/integrations/create.mdx
new file mode 100644
index 000000000..0992e91b9
--- /dev/null
+++ b/docs/api-reference/endpoints/integrations/create.mdx
@@ -0,0 +1,40 @@
+---
+title: "Create"
+openapi: "POST /api/v1/integration"
+---
+
+## Integration Parameters
+
+The integration creation endpoint is generic and can be used for all native integrations.
+For specific integration parameters for a given service, please review the respective documentation below.
+
+
+
+
+ The ID of the integration auth object for authentication with AWS.
+ Refer [Create Integration Auth](./create-auth) for more info
+
+
+ Whether the integration should be active or inactive
+
+
+ The secret name used when saving secret in AWS SSM. Used for naming and can be arbitrary.
+
+
+ The AWS region of the SSM. Example: `us-east-1`
+
+
+ The Infisical environment slug from where secrets will be synced from. Example: `dev`
+
+
+ The Infisical folder path from where secrets will be synced from. Example: `/some/path`. The root of the environment is `/`.
+
+
+
+ Coming Soon
+
+
+ Coming Soon
+
+
+
diff --git a/docs/api-reference/endpoints/integrations/delete-auth-by-id.mdx b/docs/api-reference/endpoints/integrations/delete-auth-by-id.mdx
new file mode 100644
index 000000000..5884363fc
--- /dev/null
+++ b/docs/api-reference/endpoints/integrations/delete-auth-by-id.mdx
@@ -0,0 +1,4 @@
+---
+title: "Delete Auth By ID"
+openapi: "DELETE /api/v1/integration-auth/{integrationAuthId}"
+---
diff --git a/docs/api-reference/endpoints/integrations/delete-auth.mdx b/docs/api-reference/endpoints/integrations/delete-auth.mdx
new file mode 100644
index 000000000..93d957903
--- /dev/null
+++ b/docs/api-reference/endpoints/integrations/delete-auth.mdx
@@ -0,0 +1,4 @@
+---
+title: "Delete Auth"
+openapi: "DELETE /api/v1/integration-auth"
+---
diff --git a/docs/api-reference/endpoints/integrations/delete.mdx b/docs/api-reference/endpoints/integrations/delete.mdx
new file mode 100644
index 000000000..51df56de7
--- /dev/null
+++ b/docs/api-reference/endpoints/integrations/delete.mdx
@@ -0,0 +1,4 @@
+---
+title: "Delete"
+openapi: "DELETE /api/v1/integration/{integrationId}"
+---
diff --git a/docs/api-reference/endpoints/integrations/find-auth.mdx b/docs/api-reference/endpoints/integrations/find-auth.mdx
new file mode 100644
index 000000000..439b82935
--- /dev/null
+++ b/docs/api-reference/endpoints/integrations/find-auth.mdx
@@ -0,0 +1,4 @@
+---
+title: "Get Auth By ID"
+openapi: "GET /api/v1/integration-auth/{integrationAuthId}"
+---
diff --git a/docs/api-reference/endpoints/integrations/list-auth.mdx b/docs/api-reference/endpoints/integrations/list-auth.mdx
new file mode 100644
index 000000000..3ca961d98
--- /dev/null
+++ b/docs/api-reference/endpoints/integrations/list-auth.mdx
@@ -0,0 +1,4 @@
+---
+title: "List Auth"
+openapi: "GET /api/v1/workspace/{workspaceId}/authorizations"
+---
diff --git a/docs/api-reference/endpoints/integrations/update.mdx b/docs/api-reference/endpoints/integrations/update.mdx
new file mode 100644
index 000000000..8567c46ae
--- /dev/null
+++ b/docs/api-reference/endpoints/integrations/update.mdx
@@ -0,0 +1,4 @@
+---
+title: "Update"
+openapi: "PATCH /api/v1/integration/{integrationId}"
+---
diff --git a/docs/mint.json b/docs/mint.json
index 9d9759f0e..4f70fb4c4 100644
--- a/docs/mint.json
+++ b/docs/mint.json
@@ -1,6 +1,6 @@
{
"name": "Infisical",
- "openapi": "https://app.infisical.com/api/docs/json",
+ "openapi": "http://localhost:8080/api/docs/json",
"logo": {
"dark": "/logo/dark.svg",
"light": "/logo/light.svg",
@@ -32,7 +32,10 @@
"thumbsRating": true
},
"api": {
- "baseUrl": ["https://app.infisical.com", "http://localhost:8080"]
+ "baseUrl": [
+ "https://app.infisical.com",
+ "http://localhost:8080"
+ ]
},
"topbarLinks": [
{
@@ -279,7 +282,7 @@
"integrations/cloud/azure-key-vault",
"integrations/cloud/gcp-secret-manager",
{
- "group": "Cloudflare",
+ "group": "Cloudflare",
"pages": [
"integrations/cloud/cloudflare-pages",
"integrations/cloud/cloudflare-workers"
@@ -356,14 +359,16 @@
},
{
"group": "Build Tool Integrations",
- "pages": ["integrations/build-tools/gradle"]
+ "pages": [
+ "integrations/build-tools/gradle"
+ ]
},
{
"group": "",
"pages": [
"sdks/overview"
]
- },
+ },
{
"group": "SDK's",
"pages": [
@@ -494,13 +499,30 @@
"api-reference/endpoints/secret-imports/delete"
]
},
+ {
+ "group": "Integrations",
+ "pages": [
+ "api-reference/endpoints/integrations/create-auth",
+ "api-reference/endpoints/integrations/list-auth",
+ "api-reference/endpoints/integrations/find-auth",
+ "api-reference/endpoints/integrations/delete-auth",
+ "api-reference/endpoints/integrations/delete-auth-by-id",
+ "api-reference/endpoints/integrations/create",
+ "api-reference/endpoints/integrations/update",
+ "api-reference/endpoints/integrations/delete"
+ ]
+ },
{
"group": "Service Tokens",
- "pages": ["api-reference/endpoints/service-tokens/get"]
+ "pages": [
+ "api-reference/endpoints/service-tokens/get"
+ ]
},
{
"group": "Audit Logs",
- "pages": ["api-reference/endpoints/audit-logs/export-audit-log"]
+ "pages": [
+ "api-reference/endpoints/audit-logs/export-audit-log"
+ ]
}
]
},
@@ -516,21 +538,22 @@
},
{
"group": "",
- "pages": ["changelog/overview"]
+ "pages": [
+ "changelog/overview"
+ ]
},
{
"group": "Contributing",
"pages": [
- {
- "group": "Getting Started",
- "pages": [
- "contributing/getting-started/overview",
- "contributing/getting-started/code-of-conduct",
- "contributing/getting-started/pull-requests",
- "contributing/getting-started/faq"
-
- ]
- },
+ {
+ "group": "Getting Started",
+ "pages": [
+ "contributing/getting-started/overview",
+ "contributing/getting-started/code-of-conduct",
+ "contributing/getting-started/pull-requests",
+ "contributing/getting-started/faq"
+ ]
+ },
{
"group": "Contributing to platform",
"pages": [
@@ -540,11 +563,11 @@
]
},
{
- "group": "Contributing to SDK",
- "pages": [
- "contributing/sdk/developing"
- ]
- }
+ "group": "Contributing to SDK",
+ "pages": [
+ "contributing/sdk/developing"
+ ]
+ }
]
}
],