@checkstack/maintenance-common 0.0.3 → 0.2.0

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,156 @@
1
1
  # @checkstack/maintenance-common
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 9faec1f: # Unified AccessRule Terminology Refactoring
8
+
9
+ This release completes a comprehensive terminology refactoring from "permission" to "accessRule" across the entire codebase, establishing a consistent and modern access control vocabulary.
10
+
11
+ ## Changes
12
+
13
+ ### Core Infrastructure (`@checkstack/common`)
14
+
15
+ - Introduced `AccessRule` interface as the primary access control type
16
+ - Added `accessPair()` helper for creating read/manage access rule pairs
17
+ - Added `access()` builder for individual access rules
18
+ - Replaced `Permission` type with `AccessRule` throughout
19
+
20
+ ### API Changes
21
+
22
+ - `env.registerPermissions()` → `env.registerAccessRules()`
23
+ - `meta.permissions` → `meta.access` in RPC contracts
24
+ - `usePermission()` → `useAccess()` in frontend hooks
25
+ - Route `permission:` field → `accessRule:` field
26
+
27
+ ### UI Changes
28
+
29
+ - "Roles & Permissions" tab → "Roles & Access Rules"
30
+ - "You don't have permission..." → "You don't have access..."
31
+ - All permission-related UI text updated
32
+
33
+ ### Documentation & Templates
34
+
35
+ - Updated 18 documentation files with AccessRule terminology
36
+ - Updated 7 scaffolding templates with `accessPair()` pattern
37
+ - All code examples use new AccessRule API
38
+
39
+ ## Migration Guide
40
+
41
+ ### Backend Plugins
42
+
43
+ ```diff
44
+ - import { permissionList } from "./permissions";
45
+ - env.registerPermissions(permissionList);
46
+ + import { accessRules } from "./access";
47
+ + env.registerAccessRules(accessRules);
48
+ ```
49
+
50
+ ### RPC Contracts
51
+
52
+ ```diff
53
+ - .meta({ userType: "user", permissions: [permissions.read.id] })
54
+ + .meta({ userType: "user", access: [access.read] })
55
+ ```
56
+
57
+ ### Frontend Hooks
58
+
59
+ ```diff
60
+ - const canRead = accessApi.usePermission(permissions.read.id);
61
+ + const canRead = accessApi.useAccess(access.read);
62
+ ```
63
+
64
+ ### Routes
65
+
66
+ ```diff
67
+ - permission: permissions.entityRead.id,
68
+ + accessRule: access.read,
69
+ ```
70
+
71
+ ### Patch Changes
72
+
73
+ - Updated dependencies [9faec1f]
74
+ - Updated dependencies [f533141]
75
+ - @checkstack/common@0.2.0
76
+ - @checkstack/frontend-api@0.1.0
77
+ - @checkstack/signal-common@0.1.0
78
+
79
+ ## 0.1.0
80
+
81
+ ### Minor Changes
82
+
83
+ - 8e43507: # Teams and Resource-Level Access Control
84
+
85
+ This release introduces a comprehensive Teams system for organizing users and controlling access to resources at a granular level.
86
+
87
+ ## Features
88
+
89
+ ### Team Management
90
+
91
+ - Create, update, and delete teams with name and description
92
+ - Add/remove users from teams
93
+ - Designate team managers with elevated privileges
94
+ - View team membership and manager status
95
+
96
+ ### Resource-Level Access Control
97
+
98
+ - Grant teams access to specific resources (systems, health checks, incidents, maintenances)
99
+ - Configure read-only or manage permissions per team
100
+ - Resource-level "Team Only" mode that restricts access exclusively to team members
101
+ - Separate `resourceAccessSettings` table for resource-level settings (not per-grant)
102
+ - Automatic cleanup of grants when teams are deleted (database cascade)
103
+
104
+ ### Middleware Integration
105
+
106
+ - Extended `autoAuthMiddleware` to support resource access checks
107
+ - Single-resource pre-handler validation for detail endpoints
108
+ - Automatic list filtering for collection endpoints
109
+ - S2S endpoints for access verification
110
+
111
+ ### Frontend Components
112
+
113
+ - `TeamsTab` component for managing teams in Auth Settings
114
+ - `TeamAccessEditor` component for assigning team access to resources
115
+ - Resource-level "Team Only" toggle in `TeamAccessEditor`
116
+ - Integration into System, Health Check, Incident, and Maintenance editors
117
+
118
+ ## Breaking Changes
119
+
120
+ ### API Response Format Changes
121
+
122
+ List endpoints now return objects with named keys instead of arrays directly:
123
+
124
+ ```typescript
125
+ // Before
126
+ const systems = await catalogApi.getSystems();
127
+
128
+ // After
129
+ const { systems } = await catalogApi.getSystems();
130
+ ```
131
+
132
+ Affected endpoints:
133
+
134
+ - `catalog.getSystems` → `{ systems: [...] }`
135
+ - `healthcheck.getConfigurations` → `{ configurations: [...] }`
136
+ - `incident.listIncidents` → `{ incidents: [...] }`
137
+ - `maintenance.listMaintenances` → `{ maintenances: [...] }`
138
+
139
+ ### User Identity Enrichment
140
+
141
+ `RealUser` and `ApplicationUser` types now include `teamIds: string[]` field with team memberships.
142
+
143
+ ## Documentation
144
+
145
+ See `docs/backend/teams.md` for complete API reference and integration guide.
146
+
147
+ ### Patch Changes
148
+
149
+ - Updated dependencies [8e43507]
150
+ - @checkstack/common@0.1.0
151
+ - @checkstack/frontend-api@0.0.4
152
+ - @checkstack/signal-common@0.0.4
153
+
3
154
  ## 0.0.3
4
155
 
5
156
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkstack/maintenance-common",
3
- "version": "0.0.3",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
package/src/access.ts ADDED
@@ -0,0 +1,31 @@
1
+ import { accessPair } from "@checkstack/common";
2
+
3
+ /**
4
+ * Access rules for the Maintenance plugin.
5
+ */
6
+ export const maintenanceAccess = {
7
+ /**
8
+ * Maintenance access with both read and manage levels.
9
+ * Read is public by default.
10
+ */
11
+ maintenance: accessPair(
12
+ "maintenance",
13
+ {
14
+ read: "View planned maintenances",
15
+ manage:
16
+ "Manage planned maintenances - create, edit, delete, and add updates",
17
+ },
18
+ {
19
+ readIsDefault: true,
20
+ readIsPublic: true,
21
+ }
22
+ ),
23
+ };
24
+
25
+ /**
26
+ * All access rules for registration with the plugin system.
27
+ */
28
+ export const maintenanceAccessRules = [
29
+ maintenanceAccess.maintenance.read,
30
+ maintenanceAccess.maintenance.manage,
31
+ ];
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { permissions, permissionList } from "./permissions";
1
+ export { maintenanceAccess, maintenanceAccessRules } from "./access";
2
2
  export {
3
3
  maintenanceContract,
4
4
  MaintenanceApi,
@@ -4,7 +4,7 @@ import {
4
4
  createClientDefinition,
5
5
  type ProcedureMetadata,
6
6
  } from "@checkstack/common";
7
- import { permissions } from "./permissions";
7
+ import { maintenanceAccess } from "./access";
8
8
  import { pluginMetadata } from "./plugin-metadata";
9
9
  import {
10
10
  MaintenanceWithSystemsSchema,
@@ -23,7 +23,7 @@ export const maintenanceContract = {
23
23
  listMaintenances: _base
24
24
  .meta({
25
25
  userType: "public",
26
- permissions: [permissions.maintenanceRead.id],
26
+ access: [maintenanceAccess.maintenance.read],
27
27
  })
28
28
  .input(
29
29
  z
@@ -33,13 +33,13 @@ export const maintenanceContract = {
33
33
  })
34
34
  .optional()
35
35
  )
36
- .output(z.array(MaintenanceWithSystemsSchema)),
36
+ .output(z.object({ maintenances: z.array(MaintenanceWithSystemsSchema) })),
37
37
 
38
38
  /** Get a single maintenance with all details */
39
39
  getMaintenance: _base
40
40
  .meta({
41
41
  userType: "public",
42
- permissions: [permissions.maintenanceRead.id],
42
+ access: [maintenanceAccess.maintenance.read],
43
43
  })
44
44
  .input(z.object({ id: z.string() }))
45
45
  .output(MaintenanceDetailSchema.nullable()),
@@ -48,7 +48,7 @@ export const maintenanceContract = {
48
48
  getMaintenancesForSystem: _base
49
49
  .meta({
50
50
  userType: "public",
51
- permissions: [permissions.maintenanceRead.id],
51
+ access: [maintenanceAccess.maintenance.read],
52
52
  })
53
53
  .input(z.object({ systemId: z.string() }))
54
54
  .output(z.array(MaintenanceWithSystemsSchema)),
@@ -57,7 +57,7 @@ export const maintenanceContract = {
57
57
  createMaintenance: _base
58
58
  .meta({
59
59
  userType: "authenticated",
60
- permissions: [permissions.maintenanceManage.id],
60
+ access: [maintenanceAccess.maintenance.manage],
61
61
  })
62
62
  .input(CreateMaintenanceInputSchema)
63
63
  .output(MaintenanceWithSystemsSchema),
@@ -66,7 +66,7 @@ export const maintenanceContract = {
66
66
  updateMaintenance: _base
67
67
  .meta({
68
68
  userType: "authenticated",
69
- permissions: [permissions.maintenanceManage.id],
69
+ access: [maintenanceAccess.maintenance.manage],
70
70
  })
71
71
  .input(UpdateMaintenanceInputSchema)
72
72
  .output(MaintenanceWithSystemsSchema),
@@ -75,7 +75,7 @@ export const maintenanceContract = {
75
75
  addUpdate: _base
76
76
  .meta({
77
77
  userType: "authenticated",
78
- permissions: [permissions.maintenanceManage.id],
78
+ access: [maintenanceAccess.maintenance.manage],
79
79
  })
80
80
  .input(AddMaintenanceUpdateInputSchema)
81
81
  .output(MaintenanceUpdateSchema),
@@ -84,7 +84,7 @@ export const maintenanceContract = {
84
84
  closeMaintenance: _base
85
85
  .meta({
86
86
  userType: "authenticated",
87
- permissions: [permissions.maintenanceManage.id],
87
+ access: [maintenanceAccess.maintenance.manage],
88
88
  })
89
89
  .input(z.object({ id: z.string(), message: z.string().optional() }))
90
90
  .output(MaintenanceWithSystemsSchema),
@@ -93,7 +93,7 @@ export const maintenanceContract = {
93
93
  deleteMaintenance: _base
94
94
  .meta({
95
95
  userType: "authenticated",
96
- permissions: [permissions.maintenanceManage.id],
96
+ access: [maintenanceAccess.maintenance.manage],
97
97
  })
98
98
  .input(z.object({ id: z.string() }))
99
99
  .output(z.object({ success: z.boolean() })),
@@ -1,19 +0,0 @@
1
- import { createPermission, type Permission } from "@checkstack/common";
2
-
3
- export const permissions = {
4
- /** Read access to maintenances - granted to all authenticated users by default */
5
- maintenanceRead: createPermission(
6
- "maintenance",
7
- "read",
8
- "View planned maintenances",
9
- { isAuthenticatedDefault: true, isPublicDefault: true }
10
- ),
11
- /** Manage maintenances - create, edit, delete, and add updates */
12
- maintenanceManage: createPermission(
13
- "maintenance",
14
- "manage",
15
- "Manage planned maintenances"
16
- ),
17
- } as const satisfies Record<string, Permission>;
18
-
19
- export const permissionList = Object.values(permissions);