@backstage/backend-defaults 0.17.6-next.1 → 0.17.7-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @backstage/backend-defaults
2
2
 
3
+ ## 0.17.7-next.2
4
+
5
+ ### Patch Changes
6
+
7
+ - b1b6c80: Read-only actions now default to non-destructive when the destructive attribute is omitted.
8
+ - 78bf918: chore(deps): bump `tar` from 7.5.15 to 7.5.21
9
+ - bb98419: TypeScript configuration schema warnings discovered while setting up secret redaction are now reported through the Backstage logger.
10
+ - Updated dependencies
11
+ - @backstage/config-loader@1.11.2-next.0
12
+ - @backstage/backend-plugin-api@1.10.0-next.1
13
+
3
14
  ## 0.17.6-next.1
4
15
 
5
16
  ### Patch Changes
@@ -434,7 +434,7 @@
434
434
  "properties": {
435
435
  "destructive": {
436
436
  "type": "boolean",
437
- "description": "If specified, only match actions where destructive matches this value. Actions default to destructive: true if not explicitly set."
437
+ "description": "If specified, only match actions where destructive matches this value. Actions default to destructive: false when readOnly is true, and destructive: true otherwise."
438
438
  },
439
439
  "readOnly": {
440
440
  "type": "boolean",
@@ -468,7 +468,7 @@
468
468
  "properties": {
469
469
  "destructive": {
470
470
  "type": "boolean",
471
- "description": "If specified, only match actions where destructive matches this value. Actions default to destructive: true if not explicitly set."
471
+ "description": "If specified, only match actions where destructive matches this value. Actions default to destructive: false when readOnly is true, and destructive: true otherwise."
472
472
  },
473
473
  "readOnly": {
474
474
  "type": "boolean",
@@ -2104,7 +2104,7 @@
2104
2104
  "level"
2105
2105
  ]
2106
2106
  },
2107
- "description": "List of logger overrides.\n\nCan be used to configure a different level for logs matching certain criterias. For example, it can be used to ignore 'info' logs of given plugins."
2107
+ "description": "List of logger overrides.\n\nCan be used to configure a different level for logs matching certain criteria. For example, it can be used to ignore 'info' logs of given plugins."
2108
2108
  }
2109
2109
  },
2110
2110
  "description": "Options to configure the default RootLoggerService."
@@ -65,7 +65,7 @@ class DefaultActionsRegistryService {
65
65
  attributes: {
66
66
  // Inspired by the @modelcontextprotocol/sdk defaults for the hints.
67
67
  // https://github.com/modelcontextprotocol/typescript-sdk/blob/dd69efa1de8646bb6b195ff8d5f52e13739f4550/src/types.ts#L777-L812
68
- destructive: action.attributes?.destructive ?? true,
68
+ destructive: action.attributes?.destructive ?? !action.attributes?.readOnly,
69
69
  idempotent: action.attributes?.idempotent ?? false,
70
70
  readOnly: action.attributes?.readOnly ?? false
71
71
  },
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultActionsRegistryService.cjs.js","sources":["../../../../src/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthService,\n BackstageCredentials,\n HttpAuthService,\n LoggerService,\n PermissionsRegistryService,\n PermissionsService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport PromiseRouter from 'express-promise-router';\nimport { Router, json } from 'express';\nimport { z, AnyZodObject } from 'zod/v3';\nimport zodToJsonSchema from 'zod-to-json-schema';\nimport {\n ActionsRegistryActionOptions,\n ActionsRegistryService,\n} from '@backstage/backend-plugin-api/alpha';\nimport { InputError, NotAllowedError, NotFoundError } from '@backstage/errors';\nimport { AuthorizeResult } from '@backstage/plugin-permission-common';\n\ntype ActionEntry = [string, ActionsRegistryActionOptions<any, any, any>];\n\nexport class DefaultActionsRegistryService implements ActionsRegistryService {\n private actions: Map<string, ActionsRegistryActionOptions<any, any, any>> =\n new Map();\n\n private readonly logger: LoggerService;\n private readonly httpAuth: HttpAuthService;\n private readonly auth: AuthService;\n private readonly metadata: PluginMetadataService;\n private readonly permissions: PermissionsService;\n private readonly permissionsRegistry: PermissionsRegistryService;\n\n private constructor(\n logger: LoggerService,\n httpAuth: HttpAuthService,\n auth: AuthService,\n metadata: PluginMetadataService,\n permissions: PermissionsService,\n permissionsRegistry: PermissionsRegistryService,\n ) {\n this.logger = logger;\n this.httpAuth = httpAuth;\n this.auth = auth;\n this.metadata = metadata;\n this.permissions = permissions;\n this.permissionsRegistry = permissionsRegistry;\n }\n\n static create({\n httpAuth,\n logger,\n auth,\n metadata,\n permissions,\n permissionsRegistry,\n }: {\n httpAuth: HttpAuthService;\n logger: LoggerService;\n auth: AuthService;\n metadata: PluginMetadataService;\n permissions: PermissionsService;\n permissionsRegistry: PermissionsRegistryService;\n }): DefaultActionsRegistryService {\n return new DefaultActionsRegistryService(\n logger,\n httpAuth,\n auth,\n metadata,\n permissions,\n permissionsRegistry,\n );\n }\n\n createRouter(): Router {\n const router = PromiseRouter();\n router.use('/.backstage/actions/', json());\n\n router.get('/.backstage/actions/v1/actions', async (req, res) => {\n const credentials = await this.httpAuth.credentials(req);\n const entries = Array.from(this.actions.entries());\n\n const allowedActions = await this.filterByPermissions(\n entries,\n credentials,\n );\n\n return res.json({\n actions: allowedActions.map(([id, action]) => ({\n id,\n name: action.name,\n title: action.title,\n description: action.description,\n pluginId: this.metadata.getId(),\n attributes: {\n // Inspired by the @modelcontextprotocol/sdk defaults for the hints.\n // https://github.com/modelcontextprotocol/typescript-sdk/blob/dd69efa1de8646bb6b195ff8d5f52e13739f4550/src/types.ts#L777-L812\n destructive: action.attributes?.destructive ?? true,\n idempotent: action.attributes?.idempotent ?? false,\n readOnly: action.attributes?.readOnly ?? false,\n },\n examples: action.examples,\n schema: {\n input: action.schema?.input\n ? zodToJsonSchema(action.schema.input(z))\n : zodToJsonSchema(z.object({})),\n output: action.schema?.output\n ? zodToJsonSchema(action.schema.output(z))\n : zodToJsonSchema(z.object({})),\n ...(action.schema?.secrets && {\n secrets: zodToJsonSchema(action.schema.secrets(z)),\n }),\n },\n })),\n });\n });\n\n const invokeHandler =\n (opts: { wrapped: boolean }) =>\n async (\n req: import('express').Request,\n res: import('express').Response,\n ) => {\n const credentials = await this.httpAuth.credentials(req);\n if (this.auth.isPrincipal(credentials, 'none')) {\n throw new NotAllowedError(\n `Actions must be invoked by an authenticated principal, not an anonymous request`,\n );\n }\n\n const action = this.actions.get(req.params.actionId);\n\n if (!action) {\n throw new NotFoundError(`Action \"${req.params.actionId}\" not found`);\n }\n\n if (action.visibilityPermission) {\n const [decision] = await this.permissions.authorize(\n [{ permission: action.visibilityPermission }],\n { credentials },\n );\n if (decision.result !== AuthorizeResult.ALLOW) {\n throw new NotFoundError(\n `Action \"${req.params.actionId}\" not found`,\n );\n }\n }\n\n const rawInput = opts.wrapped ? req.body.input : req.body;\n const rawSecrets = opts.wrapped ? req.body.secrets : undefined;\n\n const input = action.schema?.input\n ? action.schema.input(z).safeParse(rawInput)\n : ({ success: true, data: undefined } as const);\n\n if (!input.success) {\n throw new InputError(\n `Invalid input to action \"${req.params.actionId}\"`,\n input.error,\n );\n }\n\n if (action.schema?.secrets && !rawSecrets) {\n throw new InputError(\n `Action \"${req.params.actionId}\" requires secrets but none were provided`,\n );\n }\n\n if (!action.schema?.secrets && rawSecrets) {\n throw new InputError(\n `Action \"${req.params.actionId}\" does not accept secrets`,\n );\n }\n\n const secrets = action.schema?.secrets\n ? action.schema.secrets(z).safeParse(rawSecrets)\n : ({ success: true, data: undefined } as const);\n\n if (!secrets.success) {\n throw new InputError(\n `Invalid secrets for action \"${req.params.actionId}\"`,\n secrets.error,\n );\n }\n\n const result = await action.action({\n input: input.data,\n secrets: secrets.data,\n credentials,\n logger: this.logger,\n });\n\n const output = action.schema?.output\n ? action.schema.output(z).safeParse(result?.output)\n : ({ success: true, data: result?.output } as const);\n\n if (!output.success) {\n throw new InputError(\n `Invalid output from action \"${req.params.actionId}\"`,\n output.error,\n );\n }\n\n res.json({ output: output.data });\n };\n\n // Deprecated: remove v1 invoke route once all callers have migrated to v2\n router.post(\n '/.backstage/actions/v1/actions/:actionId/invoke',\n invokeHandler({ wrapped: false }),\n );\n\n router.post(\n '/.backstage/actions/v2/actions/:actionId/invoke',\n invokeHandler({ wrapped: true }),\n );\n\n return router;\n }\n\n register<\n TInputSchema extends AnyZodObject,\n TOutputSchema extends AnyZodObject,\n TSecretsSchema extends AnyZodObject | undefined = undefined,\n >(\n options: ActionsRegistryActionOptions<\n TInputSchema,\n TOutputSchema,\n TSecretsSchema\n >,\n ): void {\n const id = `${this.metadata.getId()}:${options.name}`;\n\n if (this.actions.has(id)) {\n throw new Error(`Action with id \"${id}\" is already registered`);\n }\n\n if (options.visibilityPermission) {\n this.permissionsRegistry.addPermissions([options.visibilityPermission]);\n }\n\n this.actions.set(id, options);\n }\n\n private async filterByPermissions(\n entries: ActionEntry[],\n credentials: BackstageCredentials,\n ): Promise<ActionEntry[]> {\n const permissionedEntries = entries.filter(\n ([_, action]) => action.visibilityPermission,\n );\n\n if (permissionedEntries.length === 0) {\n return entries;\n }\n\n const decisions = await this.permissions.authorize(\n permissionedEntries.map(([_, action]) => ({\n permission: action.visibilityPermission!,\n })),\n { credentials },\n );\n\n const deniedIds = new Set(\n permissionedEntries\n .filter((_, index) => decisions[index].result !== AuthorizeResult.ALLOW)\n .map(([id]) => id),\n );\n\n return entries.filter(([id]) => !deniedIds.has(id));\n }\n}\n"],"names":["PromiseRouter","json","zodToJsonSchema","z","NotAllowedError","NotFoundError","AuthorizeResult","InputError"],"mappings":"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"}
1
+ {"version":3,"file":"DefaultActionsRegistryService.cjs.js","sources":["../../../../src/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthService,\n BackstageCredentials,\n HttpAuthService,\n LoggerService,\n PermissionsRegistryService,\n PermissionsService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport PromiseRouter from 'express-promise-router';\nimport { Router, json } from 'express';\nimport { z, AnyZodObject } from 'zod/v3';\nimport zodToJsonSchema from 'zod-to-json-schema';\nimport {\n ActionsRegistryActionOptions,\n ActionsRegistryService,\n} from '@backstage/backend-plugin-api/alpha';\nimport { InputError, NotAllowedError, NotFoundError } from '@backstage/errors';\nimport { AuthorizeResult } from '@backstage/plugin-permission-common';\n\ntype ActionEntry = [string, ActionsRegistryActionOptions<any, any, any>];\n\nexport class DefaultActionsRegistryService implements ActionsRegistryService {\n private actions: Map<string, ActionsRegistryActionOptions<any, any, any>> =\n new Map();\n\n private readonly logger: LoggerService;\n private readonly httpAuth: HttpAuthService;\n private readonly auth: AuthService;\n private readonly metadata: PluginMetadataService;\n private readonly permissions: PermissionsService;\n private readonly permissionsRegistry: PermissionsRegistryService;\n\n private constructor(\n logger: LoggerService,\n httpAuth: HttpAuthService,\n auth: AuthService,\n metadata: PluginMetadataService,\n permissions: PermissionsService,\n permissionsRegistry: PermissionsRegistryService,\n ) {\n this.logger = logger;\n this.httpAuth = httpAuth;\n this.auth = auth;\n this.metadata = metadata;\n this.permissions = permissions;\n this.permissionsRegistry = permissionsRegistry;\n }\n\n static create({\n httpAuth,\n logger,\n auth,\n metadata,\n permissions,\n permissionsRegistry,\n }: {\n httpAuth: HttpAuthService;\n logger: LoggerService;\n auth: AuthService;\n metadata: PluginMetadataService;\n permissions: PermissionsService;\n permissionsRegistry: PermissionsRegistryService;\n }): DefaultActionsRegistryService {\n return new DefaultActionsRegistryService(\n logger,\n httpAuth,\n auth,\n metadata,\n permissions,\n permissionsRegistry,\n );\n }\n\n createRouter(): Router {\n const router = PromiseRouter();\n router.use('/.backstage/actions/', json());\n\n router.get('/.backstage/actions/v1/actions', async (req, res) => {\n const credentials = await this.httpAuth.credentials(req);\n const entries = Array.from(this.actions.entries());\n\n const allowedActions = await this.filterByPermissions(\n entries,\n credentials,\n );\n\n return res.json({\n actions: allowedActions.map(([id, action]) => ({\n id,\n name: action.name,\n title: action.title,\n description: action.description,\n pluginId: this.metadata.getId(),\n attributes: {\n // Inspired by the @modelcontextprotocol/sdk defaults for the hints.\n // https://github.com/modelcontextprotocol/typescript-sdk/blob/dd69efa1de8646bb6b195ff8d5f52e13739f4550/src/types.ts#L777-L812\n destructive:\n action.attributes?.destructive ?? !action.attributes?.readOnly,\n idempotent: action.attributes?.idempotent ?? false,\n readOnly: action.attributes?.readOnly ?? false,\n },\n examples: action.examples,\n schema: {\n input: action.schema?.input\n ? zodToJsonSchema(action.schema.input(z))\n : zodToJsonSchema(z.object({})),\n output: action.schema?.output\n ? zodToJsonSchema(action.schema.output(z))\n : zodToJsonSchema(z.object({})),\n ...(action.schema?.secrets && {\n secrets: zodToJsonSchema(action.schema.secrets(z)),\n }),\n },\n })),\n });\n });\n\n const invokeHandler =\n (opts: { wrapped: boolean }) =>\n async (\n req: import('express').Request,\n res: import('express').Response,\n ) => {\n const credentials = await this.httpAuth.credentials(req);\n if (this.auth.isPrincipal(credentials, 'none')) {\n throw new NotAllowedError(\n `Actions must be invoked by an authenticated principal, not an anonymous request`,\n );\n }\n\n const action = this.actions.get(req.params.actionId);\n\n if (!action) {\n throw new NotFoundError(`Action \"${req.params.actionId}\" not found`);\n }\n\n if (action.visibilityPermission) {\n const [decision] = await this.permissions.authorize(\n [{ permission: action.visibilityPermission }],\n { credentials },\n );\n if (decision.result !== AuthorizeResult.ALLOW) {\n throw new NotFoundError(\n `Action \"${req.params.actionId}\" not found`,\n );\n }\n }\n\n const rawInput = opts.wrapped ? req.body.input : req.body;\n const rawSecrets = opts.wrapped ? req.body.secrets : undefined;\n\n const input = action.schema?.input\n ? action.schema.input(z).safeParse(rawInput)\n : ({ success: true, data: undefined } as const);\n\n if (!input.success) {\n throw new InputError(\n `Invalid input to action \"${req.params.actionId}\"`,\n input.error,\n );\n }\n\n if (action.schema?.secrets && !rawSecrets) {\n throw new InputError(\n `Action \"${req.params.actionId}\" requires secrets but none were provided`,\n );\n }\n\n if (!action.schema?.secrets && rawSecrets) {\n throw new InputError(\n `Action \"${req.params.actionId}\" does not accept secrets`,\n );\n }\n\n const secrets = action.schema?.secrets\n ? action.schema.secrets(z).safeParse(rawSecrets)\n : ({ success: true, data: undefined } as const);\n\n if (!secrets.success) {\n throw new InputError(\n `Invalid secrets for action \"${req.params.actionId}\"`,\n secrets.error,\n );\n }\n\n const result = await action.action({\n input: input.data,\n secrets: secrets.data,\n credentials,\n logger: this.logger,\n });\n\n const output = action.schema?.output\n ? action.schema.output(z).safeParse(result?.output)\n : ({ success: true, data: result?.output } as const);\n\n if (!output.success) {\n throw new InputError(\n `Invalid output from action \"${req.params.actionId}\"`,\n output.error,\n );\n }\n\n res.json({ output: output.data });\n };\n\n // Deprecated: remove v1 invoke route once all callers have migrated to v2\n router.post(\n '/.backstage/actions/v1/actions/:actionId/invoke',\n invokeHandler({ wrapped: false }),\n );\n\n router.post(\n '/.backstage/actions/v2/actions/:actionId/invoke',\n invokeHandler({ wrapped: true }),\n );\n\n return router;\n }\n\n register<\n TInputSchema extends AnyZodObject,\n TOutputSchema extends AnyZodObject,\n TSecretsSchema extends AnyZodObject | undefined = undefined,\n >(\n options: ActionsRegistryActionOptions<\n TInputSchema,\n TOutputSchema,\n TSecretsSchema\n >,\n ): void {\n const id = `${this.metadata.getId()}:${options.name}`;\n\n if (this.actions.has(id)) {\n throw new Error(`Action with id \"${id}\" is already registered`);\n }\n\n if (options.visibilityPermission) {\n this.permissionsRegistry.addPermissions([options.visibilityPermission]);\n }\n\n this.actions.set(id, options);\n }\n\n private async filterByPermissions(\n entries: ActionEntry[],\n credentials: BackstageCredentials,\n ): Promise<ActionEntry[]> {\n const permissionedEntries = entries.filter(\n ([_, action]) => action.visibilityPermission,\n );\n\n if (permissionedEntries.length === 0) {\n return entries;\n }\n\n const decisions = await this.permissions.authorize(\n permissionedEntries.map(([_, action]) => ({\n permission: action.visibilityPermission!,\n })),\n { credentials },\n );\n\n const deniedIds = new Set(\n permissionedEntries\n .filter((_, index) => decisions[index].result !== AuthorizeResult.ALLOW)\n .map(([id]) => id),\n );\n\n return entries.filter(([id]) => !deniedIds.has(id));\n }\n}\n"],"names":["PromiseRouter","json","zodToJsonSchema","z","NotAllowedError","NotFoundError","AuthorizeResult","InputError"],"mappings":"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"}
@@ -7,7 +7,8 @@ async function createConfigSecretEnumerator(options) {
7
7
  const { logger, dir = process.cwd() } = options;
8
8
  const { packages } = await getPackages.getPackages(dir);
9
9
  const schema = options.schema ?? await configLoader.loadConfigSchema({
10
- dependencies: packages.map((p) => p.packageJson.name)
10
+ dependencies: packages.map((p) => p.packageJson.name),
11
+ onSchemaError: (error) => logger.warn(error.message)
11
12
  });
12
13
  return (config) => {
13
14
  const [secretsData] = schema.process(
@@ -1 +1 @@
1
- {"version":3,"file":"createConfigSecretEnumerator.cjs.js","sources":["../../../src/entrypoints/rootConfig/createConfigSecretEnumerator.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\nimport { ConfigSchema, loadConfigSchema } from '@backstage/config-loader';\nimport { getPackages } from '@manypkg/get-packages';\n\n/** @public */\nexport async function createConfigSecretEnumerator(options: {\n logger: LoggerService;\n dir?: string;\n schema?: ConfigSchema;\n}): Promise<(config: Config) => Iterable<string>> {\n const { logger, dir = process.cwd() } = options;\n const { packages } = await getPackages(dir);\n const schema =\n options.schema ??\n (await loadConfigSchema({\n dependencies: packages.map(p => p.packageJson.name),\n }));\n\n return (config: Config) => {\n const [secretsData] = schema.process(\n [{ data: config.getOptional() ?? {}, context: 'schema-enumerator' }],\n {\n visibility: ['secret'],\n ignoreSchemaErrors: true,\n },\n );\n const secrets = new Set<string>();\n JSON.parse(\n JSON.stringify(secretsData.data),\n (_, v) => typeof v === 'string' && secrets.add(v),\n );\n logger.info(\n `Found ${secrets.size} new secrets in config that will be redacted`,\n );\n return secrets;\n };\n}\n"],"names":["getPackages","loadConfigSchema"],"mappings":";;;;;AAsBA,eAAsB,6BAA6B,OAAA,EAID;AAChD,EAAA,MAAM,EAAE,MAAA,EAAQ,GAAA,GAAM,OAAA,CAAQ,GAAA,IAAM,GAAI,OAAA;AACxC,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAMA,wBAAY,GAAG,CAAA;AAC1C,EAAA,MAAM,MAAA,GACJ,OAAA,CAAQ,MAAA,IACP,MAAMC,6BAAA,CAAiB;AAAA,IACtB,cAAc,QAAA,CAAS,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,YAAY,IAAI;AAAA,GACnD,CAAA;AAEH,EAAA,OAAO,CAAC,MAAA,KAAmB;AACzB,IAAA,MAAM,CAAC,WAAW,CAAA,GAAI,MAAA,CAAO,OAAA;AAAA,MAC3B,CAAC,EAAE,IAAA,EAAM,MAAA,CAAO,WAAA,MAAiB,EAAC,EAAG,OAAA,EAAS,mBAAA,EAAqB,CAAA;AAAA,MACnE;AAAA,QACE,UAAA,EAAY,CAAC,QAAQ,CAAA;AAAA,QACrB,kBAAA,EAAoB;AAAA;AACtB,KACF;AACA,IAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAChC,IAAA,IAAA,CAAK,KAAA;AAAA,MACH,IAAA,CAAK,SAAA,CAAU,WAAA,CAAY,IAAI,CAAA;AAAA,MAC/B,CAAC,GAAG,CAAA,KAAM,OAAO,MAAM,QAAA,IAAY,OAAA,CAAQ,IAAI,CAAC;AAAA,KAClD;AACA,IAAA,MAAA,CAAO,IAAA;AAAA,MACL,CAAA,MAAA,EAAS,QAAQ,IAAI,CAAA,4CAAA;AAAA,KACvB;AACA,IAAA,OAAO,OAAA;AAAA,EACT,CAAA;AACF;;;;"}
1
+ {"version":3,"file":"createConfigSecretEnumerator.cjs.js","sources":["../../../src/entrypoints/rootConfig/createConfigSecretEnumerator.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\nimport { ConfigSchema, loadConfigSchema } from '@backstage/config-loader';\nimport { getPackages } from '@manypkg/get-packages';\n\n/** @public */\nexport async function createConfigSecretEnumerator(options: {\n logger: LoggerService;\n dir?: string;\n schema?: ConfigSchema;\n}): Promise<(config: Config) => Iterable<string>> {\n const { logger, dir = process.cwd() } = options;\n const { packages } = await getPackages(dir);\n const schema =\n options.schema ??\n (await loadConfigSchema({\n dependencies: packages.map(p => p.packageJson.name),\n onSchemaError: error => logger.warn(error.message),\n }));\n\n return (config: Config) => {\n const [secretsData] = schema.process(\n [{ data: config.getOptional() ?? {}, context: 'schema-enumerator' }],\n {\n visibility: ['secret'],\n ignoreSchemaErrors: true,\n },\n );\n const secrets = new Set<string>();\n JSON.parse(\n JSON.stringify(secretsData.data),\n (_, v) => typeof v === 'string' && secrets.add(v),\n );\n logger.info(\n `Found ${secrets.size} new secrets in config that will be redacted`,\n );\n return secrets;\n };\n}\n"],"names":["getPackages","loadConfigSchema"],"mappings":";;;;;AAsBA,eAAsB,6BAA6B,OAAA,EAID;AAChD,EAAA,MAAM,EAAE,MAAA,EAAQ,GAAA,GAAM,OAAA,CAAQ,GAAA,IAAM,GAAI,OAAA;AACxC,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAMA,wBAAY,GAAG,CAAA;AAC1C,EAAA,MAAM,MAAA,GACJ,OAAA,CAAQ,MAAA,IACP,MAAMC,6BAAA,CAAiB;AAAA,IACtB,cAAc,QAAA,CAAS,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,YAAY,IAAI,CAAA;AAAA,IAClD,aAAA,EAAe,CAAA,KAAA,KAAS,MAAA,CAAO,IAAA,CAAK,MAAM,OAAO;AAAA,GAClD,CAAA;AAEH,EAAA,OAAO,CAAC,MAAA,KAAmB;AACzB,IAAA,MAAM,CAAC,WAAW,CAAA,GAAI,MAAA,CAAO,OAAA;AAAA,MAC3B,CAAC,EAAE,IAAA,EAAM,MAAA,CAAO,WAAA,MAAiB,EAAC,EAAG,OAAA,EAAS,mBAAA,EAAqB,CAAA;AAAA,MACnE;AAAA,QACE,UAAA,EAAY,CAAC,QAAQ,CAAA;AAAA,QACrB,kBAAA,EAAoB;AAAA;AACtB,KACF;AACA,IAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAChC,IAAA,IAAA,CAAK,KAAA;AAAA,MACH,IAAA,CAAK,SAAA,CAAU,WAAA,CAAY,IAAI,CAAA;AAAA,MAC/B,CAAC,GAAG,CAAA,KAAM,OAAO,MAAM,QAAA,IAAY,OAAA,CAAQ,IAAI,CAAC;AAAA,KAClD;AACA,IAAA,MAAA,CAAO,IAAA;AAAA,MACL,CAAA,MAAA,EAAS,QAAQ,IAAI,CAAA,4CAAA;AAAA,KACvB;AACA,IAAA,OAAO,OAAA;AAAA,EACT,CAAA;AACF;;;;"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var version = "0.17.6-next.1";
5
+ var version = "0.17.7-next.2";
6
6
  var packageinfo = {
7
7
  version: version};
8
8
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/backend-defaults",
3
- "version": "0.17.6-next.1",
3
+ "version": "0.17.7-next.2",
4
4
  "description": "Backend defaults used by Backstage backend apps",
5
5
  "backstage": {
6
6
  "role": "node-library"
@@ -228,10 +228,10 @@
228
228
  "@azure/storage-blob": "^12.5.0",
229
229
  "@backstage/backend-app-api": "1.7.3-next.0",
230
230
  "@backstage/backend-dev-utils": "0.1.7",
231
- "@backstage/backend-plugin-api": "1.10.0-next.0",
231
+ "@backstage/backend-plugin-api": "1.10.0-next.1",
232
232
  "@backstage/cli-node": "0.3.4",
233
233
  "@backstage/config": "1.3.8",
234
- "@backstage/config-loader": "1.11.0",
234
+ "@backstage/config-loader": "1.11.2-next.0",
235
235
  "@backstage/errors": "1.3.1",
236
236
  "@backstage/integration": "2.1.0-next.0",
237
237
  "@backstage/integration-aws-node": "0.2.0",
@@ -283,7 +283,7 @@
283
283
  "rate-limit-redis": "^4.2.0",
284
284
  "raw-body": "^2.4.1",
285
285
  "selfsigned": "^2.0.0",
286
- "tar": "^7.5.6",
286
+ "tar": "^7.5.21",
287
287
  "triple-beam": "^1.4.1",
288
288
  "winston": "^3.2.1",
289
289
  "winston-transport": "^4.5.0",
@@ -294,8 +294,8 @@
294
294
  },
295
295
  "devDependencies": {
296
296
  "@aws-sdk/util-stream-node": "^3.350.0",
297
- "@backstage/backend-test-utils": "1.11.6-next.0",
298
- "@backstage/cli": "0.36.5-next.0",
297
+ "@backstage/backend-test-utils": "1.11.6-next.1",
298
+ "@backstage/cli": "0.36.5-next.1",
299
299
  "@google-cloud/cloud-sql-connector": "^1.4.0",
300
300
  "@types/archiver": "^7.0.0",
301
301
  "@types/base64-stream": "^1.0.2",
@@ -306,7 +306,6 @@
306
306
  "@types/node-forge": "^1.3.0",
307
307
  "@types/pg-format": "^1.0.5",
308
308
  "@types/yauzl": "^2.10.0",
309
- "aws-sdk-client-mock": "^4.0.0",
310
309
  "better-sqlite3": "^12.0.0",
311
310
  "get-port": "^5.1.1",
312
311
  "http-errors": "^2.0.0",