@checkstack/slo-frontend 0.5.4 → 0.5.6

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 CHANGED
@@ -1,5 +1,81 @@
1
1
  # @checkstack/slo-frontend
2
2
 
3
+ ## 0.5.6
4
+
5
+ ### Patch Changes
6
+
7
+ - dbe89ae: fix(slo): stop SLO overview cards stretching to the sidebar height
8
+
9
+ On the SLO Dashboard the card grid sits next to a taller sidebar in an
10
+ `items-stretch` layout, so the card grid was stretched to the sidebar's
11
+ height and the default `align-content` then stretched the card rows to fill
12
+ it, leaving large empty space inside each card. The card grid now uses
13
+ `content-start` so rows stay content-sized, while `h-full` on the card/anchor
14
+ still makes cards within the same row match each other.
15
+
16
+ - Updated dependencies [f9cfdae]
17
+ - @checkstack/dependency-common@1.2.5
18
+
19
+ ## 0.5.5
20
+
21
+ ### Patch Changes
22
+
23
+ - 56e7c75: Fix frontend access checks to use FULLY-QUALIFIED access-rule ids, and resolve
24
+ the anonymous role on the frontend.
25
+
26
+ Granted access-rule ids are stored fully-qualified as `{pluginId}.{ruleId}` (e.g.
27
+ `incident.incident.read`) so two plugins defining the same short rule id never
28
+ collide. The frontend, however, was checking the UNqualified id (`incident.read`)
29
+ via `isAccessRuleSatisfied`, so every check failed for any user without the `*`
30
+ (admin) grant - masked in development because dev-auth grants `*`. This silently
31
+ broke ALL non-admin frontend gating (route guards, sidebar entries, and
32
+ `useAccess`-based button/link gating).
33
+
34
+ - **`@checkstack/common`**: `AccessRule` now carries a REQUIRED owning `pluginId`;
35
+ `access()` / `accessPair()` require and stamp it; `isAccessRuleSatisfied`
36
+ qualifies the rule (`{pluginId}.{id}`, plus the manage->read escalation) and
37
+ matches ONLY the qualified form. There is intentionally NO unqualified fallback
38
+ - matching a bare id would let one plugin's grant satisfy another plugin's
39
+ identically-named rule (a cross-plugin privilege-escalation flaw). Every plugin
40
+ that defines access rules now passes its own `pluginId`.
41
+ - **`@checkstack/backend`**: `pluginManager.getAllAccessRules()` no longer strips
42
+ the `pluginId` field (the rule `id` is already fully-qualified for the DB sync).
43
+ - **Route guard** (`@checkstack/frontend` / `@checkstack/frontend-api`) now
44
+ checks the FULL rule object (so it qualifies and escalates), not a bare id.
45
+ - **Anonymous role on the frontend**: the `accessRules` procedure is now
46
+ `public`, returning the configurable anonymous role's grants to unauthenticated
47
+ callers; `useAccessRules` fetches them for guests instead of returning an empty
48
+ set. So anonymous UI now reflects exactly what the anonymous role is allowed -
49
+ which an admin can change (`isPublic` is only the seeded default).
50
+ - Incident / maintenance / SLO detail routes are now read-gated (their read rule
51
+ is an `isPublic` default, so the anonymous role holds it unless an admin
52
+ revokes it); their dashboard status signals carry that rule and render as a
53
+ link only when the viewer may open it.
54
+
55
+ **BREAKING (`@checkstack/common`):** `AccessRule.pluginId` is now REQUIRED, and
56
+ `access()` / `accessPair()` require a `pluginId` option. `isAccessRuleSatisfied`
57
+ matches ONLY the fully-qualified `{pluginId}.{ruleId}` form - the previous
58
+ unqualified fallback is removed, because it was a cross-plugin
59
+ privilege-escalation flaw. Any code constructing an `AccessRule` or calling
60
+ `access()`/`accessPair()` must supply the owning `pluginId`.
61
+
62
+ Verified live against an anonymous caller: read pages resolve (qualified match),
63
+ manage actions are denied, manage->read escalation and `*` still work.
64
+
65
+ - Updated dependencies [460ffd6]
66
+ - Updated dependencies [56e7c75]
67
+ - Updated dependencies [56e7c75]
68
+ - @checkstack/dashboard-frontend@0.8.5
69
+ - @checkstack/frontend-api@0.9.0
70
+ - @checkstack/catalog-common@2.3.4
71
+ - @checkstack/ui@1.15.1
72
+ - @checkstack/common@0.15.0
73
+ - @checkstack/dependency-common@1.2.4
74
+ - @checkstack/healthcheck-common@1.5.4
75
+ - @checkstack/slo-common@0.5.4
76
+ - @checkstack/tips-frontend@0.3.5
77
+ - @checkstack/signal-frontend@0.2.4
78
+
3
79
  ## 0.5.4
4
80
 
5
81
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkstack/slo-frontend",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "license": "Elastic-2.0",
5
5
  "type": "module",
6
6
  "main": "src/index.tsx",
@@ -13,16 +13,16 @@
13
13
  "lint:code": "eslint . --max-warnings 0"
14
14
  },
15
15
  "dependencies": {
16
- "@checkstack/catalog-common": "2.3.3",
17
- "@checkstack/common": "0.14.1",
18
- "@checkstack/dashboard-frontend": "0.8.4",
19
- "@checkstack/dependency-common": "1.2.3",
20
- "@checkstack/frontend-api": "0.8.0",
21
- "@checkstack/healthcheck-common": "1.5.3",
22
- "@checkstack/signal-frontend": "0.2.3",
23
- "@checkstack/slo-common": "0.5.3",
24
- "@checkstack/tips-frontend": "0.3.4",
25
- "@checkstack/ui": "1.15.0",
16
+ "@checkstack/catalog-common": "2.3.4",
17
+ "@checkstack/common": "0.15.0",
18
+ "@checkstack/dashboard-frontend": "0.8.5",
19
+ "@checkstack/dependency-common": "1.2.5",
20
+ "@checkstack/frontend-api": "0.9.0",
21
+ "@checkstack/healthcheck-common": "1.5.4",
22
+ "@checkstack/signal-frontend": "0.2.4",
23
+ "@checkstack/slo-common": "0.5.4",
24
+ "@checkstack/tips-frontend": "0.3.5",
25
+ "@checkstack/ui": "1.15.1",
26
26
  "date-fns": "^4.4.0",
27
27
  "lucide-react": "^1.17.0",
28
28
  "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.0"
36
+ "@checkstack/scripts": "0.6.1"
37
37
  }
38
38
  }
@@ -6,7 +6,7 @@ import {
6
6
  type SystemSignal,
7
7
  type SystemSignalsMap,
8
8
  } from "@checkstack/catalog-common";
9
- import { SloApi, sloRoutes } from "@checkstack/slo-common";
9
+ import { SloApi, sloRoutes, sloAccess } from "@checkstack/slo-common";
10
10
 
11
11
  type Props = SlotContext<typeof SystemSignalsSlot>;
12
12
 
@@ -61,6 +61,8 @@ export const SloSignalsFiller: React.FC<Props> = ({ systemIds, onSignals }) => {
61
61
  href: resolveRoute(sloRoutes.routes.detail, {
62
62
  sloId: objective.id,
63
63
  }),
64
+ // Detail page is read-gated; render as text for users without it.
65
+ accessRule: sloAccess.slo.read,
64
66
  iconName: "Target",
65
67
  });
66
68
  }
package/src/index.tsx CHANGED
@@ -47,6 +47,8 @@ export default createFrontendPlugin({
47
47
  default: m.SloDetailPage,
48
48
  })),
49
49
  title: "SLO Detail",
50
+ // Read-gated; anonymous holds this by default (isPublic), admin-revocable.
51
+ accessRule: sloAccess.slo.read,
50
52
  },
51
53
  ],
52
54
  apis: [],
@@ -82,16 +82,20 @@ const SloOverviewPageContent: React.FC = () => {
82
82
  />
83
83
  ) : (
84
84
  <div className="grid grid-cols-1 lg:grid-cols-[1fr_300px] gap-6">
85
- <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
85
+ {/* content-start: this grid is stretched to the sidebar's height by
86
+ the outer items-stretch grid; without it, the default align-content
87
+ stretches the card rows to fill that height. Keep cards content-sized
88
+ while h-full still makes cards within a row match each other. */}
89
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4 content-start">
86
90
  {objectives.map((item) => (
87
91
  <Link
88
92
  key={item.objective.id}
89
93
  to={resolveRoute(sloRoutes.routes.detail, {
90
94
  sloId: item.objective.id,
91
95
  })}
92
- className="block no-underline"
96
+ className="block no-underline h-full"
93
97
  >
94
- <Card className="transition-colors hover:border-primary/50">
98
+ <Card className="h-full transition-colors hover:border-primary/50">
95
99
  <CardHeader className="pb-3">
96
100
  <div className="flex items-center justify-between">
97
101
  <CardTitle className="text-sm font-medium">