关于 vtex-io-app-settings
这是面向 VTEX IO 开发者的技能,帮助设计和审查应用设置边界。内容涵盖设置模式、运行时读取、默认值验证与敏感信息保护。
主要功能
- 01区分应用设置与区块配置
- 02用 JSON Schema 定义设置
- 03验证或补齐缺失配置
- 04将密钥限制在后端
- 05判断设置与配置应用的适用场景
适用场景
- 01为商家定义可管理的应用选项
- 02审查设置是否应按页面或区块变化
- 03实现安全的密钥读取与使用
- 04排查工作区设置缺失或不一致
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ vtex/ skills --skill vtex-io-app-settings安装后在 Claude Code 中输入/vtex-io-app-settings确认已加载。
详细介绍
应用设置与配置边界
何时使用此技能
在决定或实现 VTEX IO 应用应如何公开可配置设置时,使用此技能。
- 定义
settingsSchema - 添加商家可配置的应用行为
- 审查配置应属于应用设置还是自定义数据
- 在应用代码中读取和验证设置
请勿将此技能用于:
service.json中的运行时基础设施设置- Master Data 实体设计
- 策略声明详情
- 路由身份验证建模
决策规则
- 对于商家或运营人员应能明确管理的稳定配置,请使用应用设置。
- 对于通过 VTEX Admin 管理的应用级配置,请使用
settingsSchema;对于因页面或区块实例而异的 Store Framework 区块配置,请使用store/contentSchemas.json。 - 如果某个值适用于整个应用或账户,通常应放在
settingsSchema中。如果它因页面、区块或主题组合而异,通常应放在contentSchemas.json中。 - 请勿将应用设置用作高容量运营数据的替代存储。
- 请明确使用 JSON Schema 的
properties、required、default、enum、format及相关约束,而不要只使用通用的根级type: object。 - 仅对非敏感且有意通过
publicSettingsForApp安全地向前端代码公开的值,使用settingsSchema.access: "public"。 - 如果省略
access,请勿假设前端 GraphQL 消费者可以读取这些设置。必须明确选择是否允许前端公开访问。 - 对于 API 密钥、令牌和机密,请使用应用设置,而不要将它们硬编码在代码库中。
- 切勿在 HTTP 响应、GraphQL 响应、HTML 或浏览器端属性中直接公开应用设置中的机密。
- 也切勿在日志中公开应用设置中的机密。
- 对于 API 密钥或密码等敏感字段,请将其设为
type: "string",并考虑将其标记为format: "password"。某些平台消费者(例如使用hidePasswords时的 Apps GraphQL)可能会利用此元数据屏蔽响应中的值。不要将其视为唯一的安全层:机密仍必须仅供后端使用,绝不能出现在响应或日志中。 - 某些渲染器可能支持
ui:widget: "password"等 UI 专用提示,但它们不属于核心 JSON Schema 保证。不要假设标准 VTEX Admin App Settings UI 会强制执行这些提示。 - 使用
ctx.clients.apps.getAppSettings(ctx.vtex.appId ?? process.env.VTEX_APP_ID)读取后端设置,并在辅助函数中集中处理规范化或验证,而不要在各个处理程序中分散使用临时访问模式。 - 在运行时读取或保存此应用自身的设置时,请使用正确的应用标识符,例如
process.env.VTEX_APP_ID或ctx.vtex.appId,并依赖应用令牌和标准应用设置权限。不要在manifest.json中声明额外的 License Manager 策略,也不要添加read-workspace-apps之类的工作区级策略或write-workspace-apps之类未公开文档的策略,来“修复” 403 错误。 - 需要配置的 Pixel 应用也应在其后端使用
ctx.clients.apps.getAppSettings(...)读取设置。如果注入的 JavaScript 必须使用某个值,只能通过access: "public"和publicSettingsForApp暴露非敏感字段,并严格将机密保留在服务端。 - 请在设置缺失或不完整时,通过验证或在使用时应用默认值,使代码具备韧性。
- 切勿假设不同账户或工作区中的设置完全相同。在开发、发布或调试期间,各个工作区可能具有不同的应用配置。
设置与配置构建器:
- 如果配置仅适用于此应用,且预期由商家在 Apps > App Settings 中编辑,请使用
settingsSchema。 - 如果配置契约需要在多个应用间共享、需要与运行时应用生命周期分开管理,或需要通过
ctx.vtex.settings直接注入服务上下文,请考虑使用单独的应用和configuration构建器。 - 如果主要目标是通过 VTEX IO 运行时上下文提供结构化服务配置,而不是由应用自行临时获取设置,请优先选择配置应用。
硬性约束
约束:可配置的应用行为必须有 schema
商家可配置的设置必须通过明确的 schema 建模,而不是使用未经验证的临时对象。
原因
没有 schema,配置就会变得含糊、难以验证,也更容易在不同环境中出错。
检测
如果代码依赖应用级配置,但不存在 schema 或验证约定,请停止并先定义它。
正确
{
"settingsSchema": {
"title": "My App Settings",
"type": "object",
"properties": {
"enableModeration": {
"title": "Enable moderation",
"type": "boolean",
"default": false,
"description": "If true, new content will require approval before going live."
},
"apiKey": {
"title": "External API key",
"type": "string",
"minLength": 1,
"description": "API key for the external moderation service.",
"format": "password"
},
"mode": {
"title": "Mode",
"type": "string",
"enum": ["sandbox", "production"],
"default": "sandbox"
}
},
"required": ["apiKey"]
}
}
错误
const settings = ctx.state.anything
约束:敏感设置必须仅限后端使用,不得暴露给前端
应用设置中存储的密钥(例如 API 密钥、令牌或密码)必须作为仅限后端使用的配置处理。
原因
应用设置是存放密钥的常见位置,但如果通过 HTTP 响应、GraphQL 载荷、HTML 或前端属性暴露这些密钥,就会造成配置泄露。
检测
如果路由、解析器或面向前端的响应返回原始设置,或包含设置中的敏感字段,请停止,并将外部调用或密钥使用完全移至后端边界。
正确
const { apiKey } = await ctx.clients.apps.getAppSettings(
ctx.vtex.appId ?? process.env.VTEX_APP_ID
)
const result = await externalClient.fetchData({ apiKey })
ctx.body = result
错误
const settings = await ctx.clients.apps.getAppSettings(
ctx.vtex.appId ?? process.env.VTEX_APP_ID
)
ctx.body = settings
约束:公开的应用设置访问绝不能暴露敏感配置
如果将 settingsSchema.access 设为 public,那么通过 publicSettingsForApp 暴露的设置必须仅包含适合发送到前端代码的值。
原因
access: "public" 是一种交付方式,而非安全控制。一旦设置被公开,店面或前端代码就可以读取它们,因此绝不能在其中包含密钥或仅限后端使用的配置。
检测
如果设置 schema 将访问权限标记为公开,却包含 API 密钥、令牌、密码或任何仅用于后端集成的值,请停止并将这些设置设为私有。
正确
{
"settingsSchema": {
"title": "Public Storefront Settings",
"type": "object",
"access": "public",
"properties": {
"bannerText": {
"title": "Banner text",
"type": "string"
}
}
}
}
错误
{
"settingsSchema": {
"title": "My App Settings",
"type": "object",
"access": "public",
"properties": {
"apiKey": {
"title": "External API key",
"type": "string",
"format": "password"
}
}
}
}
约束:不得将设置用作业务数据存储
应用设置必须表示配置,而非大量可变记录。
原因
设置用于配置边界,而非事务性或大规模的业务数据。
检测
如果拟议的设置要存储类似订单、评价、日志或队列项目的记录,请停止,并将其转移到更合适的数据机制中。
正确
{
"enableModeration": true
}
错误
{
"allReviews": []
}
约束:代码必须在使用边界验证设置或提供默认值
依赖设置的代码必须能够安全处理缺失或不完整的值。
原因
不同工作区和账户之间的配置可能存在差异。假定所有设置都存在的代码会变得脆弱。
检测
如果代码读取设置时假定必填字段始终存在,却没有验证或默认值,请停止并明确处理此依赖。
正确
const rawSettings = await ctx.clients.apps.getAppSettings(
ctx.vtex.appId ?? process.env.VTEX_APP_ID
)
const settings = normalizeSettings(rawSettings)
const enabled = settings.enableModeration ?? false
错误
const enabled = settings.enableModeration.value
首选模式
使用设置存储稳定、由商家管理的配置,使用明确的 JSON Schema 属性定义设置,并在使用时进行验证或规范化。
对于密钥,应在后端读取密钥并发起外部调用,只向前端返回业务结果。
仅对有意公开的设置使用前端 GraphQL 访问,并通过 getAppSettings(...) 将仅限后端使用的设置保留在后端。
常见故障模式
- 将设置用作运行时存储。
- 只使用
type: object,却不显式声明properties和验证细节。 - 读取设置时不设置默认值或进行验证。
- 向前端暴露原始设置或机密信息。
- 设置包含仅供后端使用的值或敏感值时,将其标记为
access: "public"。 - 以纯文本形式记录设置或机密信息。
- 将 API 密钥或令牌硬编码,而不是存储在应用设置中。
- 遇到应用设置权限错误时,将
read-workspace-apps等工作区级策略或write-workspace-apps等无效策略作为通用变通方案,而不是验证正确的 appId 和标准应用设置权限。 - 需求实际是区块级 Store Framework 配置时,却使用
settingsSchema。 - 创建范围过宽或含糊不清的架构。
审查清单
- 这些数据确实应该属于应用设置吗?
-
settingsSchema是否声明了带明确类型的properties,并且仅在必要时将属性设为required? - 敏感字段是否以安全的方式表示,例如使用
format: "password"的string字段,并了解某些使用者(如带有hidePasswords的 Apps GraphQL)可能会利用这些元数据来隐藏输出? - 使用这些设置的代码是否会验证缺失值或提供默认值?
- 机密信息是否仅供后端使用,且绝不暴露给前端?
- 如果使用了
access: "public",所有公开的设置是否都确认可安全地供前端使用? - 设置的范围是否精简且经过审慎设计?