Skip to content

Commit 7e12df4

Browse files
committed
feat(plugin-security): a boot upgrade impact report for the non-access classes, raised to the administrator like the access upgrade report
At kernel:bootstrapped, beside the access upgrade report, read the customer's stored state against the registry for the classes that report does not cover, and raise the finding set through upgrade-report-delivery.ts under its own topic (system.upgrade_impact) and dedupKey: - flow, action and webhook switches: ledger orphans, suspected re-enablements by rename, and a switched-off action whose name more than one object now declares - a stored flow a packaged flow of the same name shadows, and a sys_webhook row withholding a declared webhook - overlay rows of the five O types bound to a package that no longer ships the item - a field an object extension declares that its base layer or another package's extension also declares, a stored object row bound to a package that does not own the object, and a navigation contribution whose group its app no longer has - a stored setting key its registered namespace no longer declares (the value is never read) It writes and refuses nothing; a store that cannot be read stops the report for that boot and says so. Claude-Session: https://claude.ai/code/session_01XHebWJmL3ZgbVpjM6JERNA Co-authored-by: Claude <noreply@anthropic.com>
1 parent 915e940 commit 7e12df4

5 files changed

Lines changed: 1832 additions & 0 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
'@objectstack/plugin-security': patch
3+
---
4+
5+
feat: a boot upgrade impact report for the non-access classes (flows, actions, webhooks, overlays, object extensions, navigation contributions, settings), raised to the administrator like the access upgrade report
6+
7+
Clause-②: yes (widening: a new boot report and a new notification topic, `system.upgrade_impact`; nothing is written or refused, and no existing path changes)
8+
Metadata-protocol: none
9+
10+
A package upgrade that renames, removes or collides with a name could leave the customer's stored state meaning something else, with nothing said beyond a scattered log line. At every boot, beside the access upgrade report, the security plugin now reads that state against the registry and lists:
11+
12+
- **Flow, action and webhook switches:** an activation ledger row whose name no package ships any more, and a switched-off one whose package now ships unswitched names of the same type (a suspected rename that makes the item active again). Also a switched-off action whose name more than one object now declares, because the one row switches every one of them off.
13+
- **Stored rows a package now overrides:** a stored flow whose name a package ships (the packaged flow runs, the stored one never does), and a `sys_webhook` row holding the name of a webhook a package declares (the declaration is withheld for the whole deployment).
14+
- **Overlay orphans:** a customization of a view, dashboard, report, translation or email template bound to an installed package that no longer ships the item. It keeps serving as an item of its own.
15+
- **Object extensions:** a field an extension declares that the object it extends (or another package's extension) also declares, where the last declaration silently wins. Also a stored object row bound to a package that does not own the object, because another package now ships the name, which the boot refuses to serve. And a navigation contribution whose group its app no longer has.
16+
- **Settings:** a stored value whose namespace no longer declares its key. The value is never read, and the default applies. The report never reads a value.
17+
18+
Each category logs one `error` with its fix. The finding set is raised through the same delivery as the access report, under its own topic and `dedupKey`. Under `single` it goes to the Default Organization's administrators. Under a wall it goes to the operator alone, and in-app in the organization `OS_PLATFORM_OWNER_ORGANIZATION` names when that is set. A clean boot logs one `info` line. A store that cannot be read stops the report for that boot, and it says so.

‎packages/plugins/plugin-security/src/security-plugin.ts‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import {
4747
type DeclaredSharingRuleReader,
4848
} from './access-upgrade-report.js';
4949
import { ACCESS_UPGRADE_CHECK_SERVICE, createAccessUpgradeCheck } from './access-upgrade-check.js';
50+
import { reportUpgradeImpact, SETTINGS_SERVICE, type SettingsManifestReader } from './upgrade-impact-report.js';
5051
import {
5152
explainAccessForAsker,
5253
buildContextForUser,
@@ -4759,6 +4760,30 @@ export class SecurityPlugin implements Plugin {
47594760
{ error: (e as Error)?.message },
47604761
);
47614762
}
4763+
// [#24447] The upgrade impact report: the same comparison for the
4764+
// non-access classes — flow, action and webhook switches, stored
4765+
// overlays and object rows, object extensions, navigation
4766+
// contributions and stored settings — raised the same way. It writes
4767+
// and refuses nothing. See `upgrade-impact-report.ts`.
4768+
try {
4769+
const optional = <T,>(name: string): T | undefined => {
4770+
try { return ctx.getService<T>(name) ?? undefined; } catch { return undefined; }
4771+
};
4772+
const settings = optional<Partial<SettingsManifestReader>>(SETTINGS_SERVICE);
4773+
const messaging = optional<Partial<AccessUpgradeNotifier>>('messaging');
4774+
await reportUpgradeImpact(ql as any, {
4775+
settings: typeof settings?.listManifests === 'function' ? (settings as SettingsManifestReader) : undefined,
4776+
messaging: typeof messaging?.emit === 'function' ? (messaging as AccessUpgradeNotifier) : undefined,
4777+
walled: postureEnforcesWall(this.tenancyPosture),
4778+
logger: ctx.logger,
4779+
});
4780+
} catch (e) {
4781+
ctx.logger.warn(
4782+
'[security] the upgrade impact report did not run — a switch, stored row, extension or setting an ' +
4783+
'upgrade left behind goes unreported for this boot',
4784+
{ error: (e as Error)?.message },
4785+
);
4786+
}
47624787
});
47634788
}
47644789

0 commit comments

Comments
 (0)