Skip to content

Commit d972d18

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/project-thread-kdrs5c
2 parents e92f351 + 54df640 commit d972d18

6 files changed

Lines changed: 1567 additions & 0 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
'@objectstack/plugin-security': patch
3+
'@objectstack/plugin-sharing': patch
4+
---
5+
6+
feat: at boot, an administrator is told when a package upgrade renamed, removed or collided with an access item the customer switched off, cloned or authored
7+
8+
Clause-②: yes (widening: plugin-sharing's exported `SharingRuleService` gains `listDeclaredRules()`; the report itself refuses nothing and adds no key, code or setting)
9+
Metadata-protocol: none
10+
11+
ADR-0126 §6 wall 3 says no upgrade un-makes a customer's choice. A switch-off, a clone or a sharing rule row is kept by name, so a vendor rename made a switched-off item active again under its new name, and nothing told anyone. At `kernel:bootstrapped`, beside the catalog reference report, `SecurityPlugin` now compares the customer's access state with the registry this boot registered. It covers sharing rules, permission sets, positions and capabilities, and lists:
12+
13+
- **Orphans:** activation-ledger rows (`position`, `permission`, `sharing_rule`) whose name the registry no longer resolves.
14+
- **Suspected re-enablements:** a switched-off orphan whose recorded `package_id` is P, with every name of the same type P now ships that no ledger row covers. A permission-set candidate names the positions that bind it.
15+
- **Sharing-rule collisions, per organization:** a `sys_sharing_rule` row holding a declared rule's name, so the declared rule is served nowhere in that scope. A position, permission-set or capability collision is already refused at registration or at boot.
16+
- **Broken references in the customer's items:** a permission set authored in this system naming an object, field or capability the registry lacks, and a `sys_sharing_rule` row naming an object or criteria field the registry lacks.
17+
- **Field denies a customer set lacks:** a package-shipped set that denies a field, beside a set authored in this system that grants the same object with no entry for that field. An unlisted field is visible.
18+
19+
The findings are logged once per category, as now. They are also raised to the people who can act on them:
20+
21+
- **Under `single`,** through the existing notification ingress (`messaging.emit()`, topic `security.access_upgrade`, severity `warning`), which writes a Notification Events row in Setup and the in-app inbox. It reaches the Default Organization's `admin_full_access` holders and any `OS_PLATFORM_OWNER_EMAIL` address.
22+
- The `dedupKey` is the finding set's digest, so an unchanged set notifies once, not at every boot.
23+
- With no messaging service, nobody to tell, or an emit the ingress refuses, one log line says the findings reached no administrator and names the fix for that cause.
24+
- The notification is not mandatory: the ingress has no per-emit flag, so a recipient's mute hides it. To make it mute-proof, add `security.access_upgrade` to the messaging plugin's existing `mandatoryTopics` option.
25+
- **Under `group` or `isolated`,** to the platform operator alone, by one `error` line addressed to the operator. The ledger and the catalog are deployment-level, so only the operator can act. The notification family is organization-scoped, and a walled write with no organization is refused (ADR-0131 D9); stamping an organization would hand the finding to a tenant. So no notification is attempted, and no organization is told.
26+
27+
Two limits follow from ADR-0126 §9, under which a clone records no base, and from the bare `(metadata_type, name)` ledger key:
28+
29+
- A re-enablement is **suspected** and may list several same-package candidates. Nothing records which name replaced which.
30+
- The field-deny check reads "grants the same object", not "copied from that set", so it may name an unrelated set. It is a review item.
31+
32+
"The old name carrying a clone" is carried by the switch-off half. The sanctioned ceremony is clone plus switch-off, and a clone whose base stays on is not a choice a rename un-makes. A read that fails stops the report for that boot, and nothing is judged from an unread store.
33+
34+
- **`@objectstack/plugin-sharing`:** `SharingRuleService.listDeclaredRules()` answers every declared rule with its `packageId`, or `null` when the service reads no declarations.

0 commit comments

Comments
 (0)