@checkstack/maintenance-frontend 0.8.4 → 0.8.5
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 +62 -0
- package/package.json +13 -13
- package/src/components/MaintenanceSignalsFiller.tsx +3 -0
- package/src/index.tsx +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,67 @@
|
|
|
1
1
|
# @checkstack/maintenance-frontend
|
|
2
2
|
|
|
3
|
+
## 0.8.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 56e7c75: Fix frontend access checks to use FULLY-QUALIFIED access-rule ids, and resolve
|
|
8
|
+
the anonymous role on the frontend.
|
|
9
|
+
|
|
10
|
+
Granted access-rule ids are stored fully-qualified as `{pluginId}.{ruleId}` (e.g.
|
|
11
|
+
`incident.incident.read`) so two plugins defining the same short rule id never
|
|
12
|
+
collide. The frontend, however, was checking the UNqualified id (`incident.read`)
|
|
13
|
+
via `isAccessRuleSatisfied`, so every check failed for any user without the `*`
|
|
14
|
+
(admin) grant - masked in development because dev-auth grants `*`. This silently
|
|
15
|
+
broke ALL non-admin frontend gating (route guards, sidebar entries, and
|
|
16
|
+
`useAccess`-based button/link gating).
|
|
17
|
+
|
|
18
|
+
- **`@checkstack/common`**: `AccessRule` now carries a REQUIRED owning `pluginId`;
|
|
19
|
+
`access()` / `accessPair()` require and stamp it; `isAccessRuleSatisfied`
|
|
20
|
+
qualifies the rule (`{pluginId}.{id}`, plus the manage->read escalation) and
|
|
21
|
+
matches ONLY the qualified form. There is intentionally NO unqualified fallback
|
|
22
|
+
- matching a bare id would let one plugin's grant satisfy another plugin's
|
|
23
|
+
identically-named rule (a cross-plugin privilege-escalation flaw). Every plugin
|
|
24
|
+
that defines access rules now passes its own `pluginId`.
|
|
25
|
+
- **`@checkstack/backend`**: `pluginManager.getAllAccessRules()` no longer strips
|
|
26
|
+
the `pluginId` field (the rule `id` is already fully-qualified for the DB sync).
|
|
27
|
+
- **Route guard** (`@checkstack/frontend` / `@checkstack/frontend-api`) now
|
|
28
|
+
checks the FULL rule object (so it qualifies and escalates), not a bare id.
|
|
29
|
+
- **Anonymous role on the frontend**: the `accessRules` procedure is now
|
|
30
|
+
`public`, returning the configurable anonymous role's grants to unauthenticated
|
|
31
|
+
callers; `useAccessRules` fetches them for guests instead of returning an empty
|
|
32
|
+
set. So anonymous UI now reflects exactly what the anonymous role is allowed -
|
|
33
|
+
which an admin can change (`isPublic` is only the seeded default).
|
|
34
|
+
- Incident / maintenance / SLO detail routes are now read-gated (their read rule
|
|
35
|
+
is an `isPublic` default, so the anonymous role holds it unless an admin
|
|
36
|
+
revokes it); their dashboard status signals carry that rule and render as a
|
|
37
|
+
link only when the viewer may open it.
|
|
38
|
+
|
|
39
|
+
**BREAKING (`@checkstack/common`):** `AccessRule.pluginId` is now REQUIRED, and
|
|
40
|
+
`access()` / `accessPair()` require a `pluginId` option. `isAccessRuleSatisfied`
|
|
41
|
+
matches ONLY the fully-qualified `{pluginId}.{ruleId}` form - the previous
|
|
42
|
+
unqualified fallback is removed, because it was a cross-plugin
|
|
43
|
+
privilege-escalation flaw. Any code constructing an `AccessRule` or calling
|
|
44
|
+
`access()`/`accessPair()` must supply the owning `pluginId`.
|
|
45
|
+
|
|
46
|
+
Verified live against an anonymous caller: read pages resolve (qualified match),
|
|
47
|
+
manage actions are denied, manage->read escalation and `*` still work.
|
|
48
|
+
|
|
49
|
+
- Updated dependencies [0626782]
|
|
50
|
+
- Updated dependencies [460ffd6]
|
|
51
|
+
- Updated dependencies [56e7c75]
|
|
52
|
+
- Updated dependencies [56e7c75]
|
|
53
|
+
- @checkstack/auth-frontend@0.7.5
|
|
54
|
+
- @checkstack/dashboard-frontend@0.8.5
|
|
55
|
+
- @checkstack/frontend-api@0.9.0
|
|
56
|
+
- @checkstack/notification-frontend@0.5.5
|
|
57
|
+
- @checkstack/catalog-common@2.3.4
|
|
58
|
+
- @checkstack/ui@1.15.1
|
|
59
|
+
- @checkstack/common@0.15.0
|
|
60
|
+
- @checkstack/maintenance-common@1.4.4
|
|
61
|
+
- @checkstack/notification-common@1.3.3
|
|
62
|
+
- @checkstack/tips-frontend@0.3.5
|
|
63
|
+
- @checkstack/signal-frontend@0.2.4
|
|
64
|
+
|
|
3
65
|
## 0.8.4
|
|
4
66
|
|
|
5
67
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@checkstack/maintenance-frontend",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.5",
|
|
4
4
|
"license": "Elastic-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.tsx",
|
|
@@ -13,17 +13,17 @@
|
|
|
13
13
|
"lint:code": "eslint . --max-warnings 0"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@checkstack/auth-frontend": "0.7.
|
|
17
|
-
"@checkstack/catalog-common": "2.3.
|
|
18
|
-
"@checkstack/common": "0.
|
|
19
|
-
"@checkstack/dashboard-frontend": "0.8.
|
|
20
|
-
"@checkstack/frontend-api": "0.
|
|
21
|
-
"@checkstack/maintenance-common": "1.4.
|
|
22
|
-
"@checkstack/notification-common": "1.3.
|
|
23
|
-
"@checkstack/notification-frontend": "0.5.
|
|
24
|
-
"@checkstack/signal-frontend": "0.2.
|
|
25
|
-
"@checkstack/tips-frontend": "0.3.
|
|
26
|
-
"@checkstack/ui": "1.15.
|
|
16
|
+
"@checkstack/auth-frontend": "0.7.5",
|
|
17
|
+
"@checkstack/catalog-common": "2.3.4",
|
|
18
|
+
"@checkstack/common": "0.15.0",
|
|
19
|
+
"@checkstack/dashboard-frontend": "0.8.5",
|
|
20
|
+
"@checkstack/frontend-api": "0.9.0",
|
|
21
|
+
"@checkstack/maintenance-common": "1.4.4",
|
|
22
|
+
"@checkstack/notification-common": "1.3.3",
|
|
23
|
+
"@checkstack/notification-frontend": "0.5.5",
|
|
24
|
+
"@checkstack/signal-frontend": "0.2.4",
|
|
25
|
+
"@checkstack/tips-frontend": "0.3.5",
|
|
26
|
+
"@checkstack/ui": "1.15.1",
|
|
27
27
|
"date-fns": "^4.4.0",
|
|
28
28
|
"lucide-react": "^1.17.0",
|
|
29
29
|
"react": "19.2.7",
|
|
@@ -33,6 +33,6 @@
|
|
|
33
33
|
"typescript": "^5.0.0",
|
|
34
34
|
"@types/react": "^19.0.0",
|
|
35
35
|
"@checkstack/tsconfig": "0.0.7",
|
|
36
|
-
"@checkstack/scripts": "0.6.
|
|
36
|
+
"@checkstack/scripts": "0.6.1"
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
MaintenanceApi,
|
|
11
11
|
maintenanceRoutes,
|
|
12
|
+
maintenanceAccess,
|
|
12
13
|
} from "@checkstack/maintenance-common";
|
|
13
14
|
|
|
14
15
|
type Props = SlotContext<typeof SystemSignalsSlot>;
|
|
@@ -51,6 +52,8 @@ export const MaintenanceSignalsFiller: React.FC<Props> = ({
|
|
|
51
52
|
href: resolveRoute(maintenanceRoutes.routes.detail, {
|
|
52
53
|
maintenanceId: maintenance.id,
|
|
53
54
|
}),
|
|
55
|
+
// Detail page is read-gated; render as text for users without it.
|
|
56
|
+
accessRule: maintenanceAccess.maintenance.read,
|
|
54
57
|
since: new Date(maintenance.startAt).toISOString(),
|
|
55
58
|
iconName: "Wrench",
|
|
56
59
|
}));
|
package/src/index.tsx
CHANGED
|
@@ -44,6 +44,8 @@ export default createFrontendPlugin({
|
|
|
44
44
|
default: m.MaintenanceDetailPage,
|
|
45
45
|
})),
|
|
46
46
|
title: "Maintenance Details",
|
|
47
|
+
// Read-gated; anonymous holds this by default (isPublic), admin-revocable.
|
|
48
|
+
accessRule: maintenanceAccess.maintenance.read,
|
|
47
49
|
},
|
|
48
50
|
],
|
|
49
51
|
// No APIs needed - components use usePluginClient() directly
|