doc/plans/2026-04-26-plugin-secret-ref-company-scope.md
Date: 2026-04-26 Status: follow-up after fail-closed mitigation Related issue: PAP-2394
PAP-2394 now fails closed:
POST /api/plugins/:pluginId/config rejects any config containing plugin secret refs.ctx.secrets.resolve() is disabled for plugin workers.This removes the release-blocking cross-company exposure path, but it also disables plugin secret-ref support until the runtime carries company scope end to end.
The original design mixed an instance-global config store with company-scoped secret bindings:
company_secret_bindings grouped by each referenced secret's owning company.pluginId + secret UUID, with no active company context from the bridge call.ctx.config.get() and ctx.secrets.resolve() without a company parameter.This violated Least Privilege, Complete Mediation, and Secure Defaults.
Re-enable plugin secret refs only after both of these are true:
company_id to plugin_config, with a unique index on (plugin_id, company_id).companyId for getConfig, upsertConfig, patchConfig, and deleteConfig.companyId and call assertCompanyAccess(req, companyId).ctx.config.get() and ctx.secrets.resolve() can receive or derive companyId.getDataperformAction(companyId, pluginId, configPath)(companyId, pluginId) target.plugin_config rows need a migration strategy before re-enable.