@checkstack/notification-common 1.2.1 → 1.3.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,66 @@
1
1
  # @checkstack/notification-common
2
2
 
3
+ ## 1.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 9dcc848: Plugin-owned AI tools: every domain plugin contributes its own AI tools (chat assistant + automation AI action), and `ai-backend` is platform-only.
8
+
9
+ Every plugin-specific AI tool is owned by the plugin whose domain it acts on, registered via that plugin's own `aiToolExtensionPoint` / `aiToolProjectionExtensionPoint` from its init - the same path an external plugin author uses. `ai-backend` no longer imports or depends on any capability plugin's `*-common`; the dependency direction is strictly plugin -> ai-platform. Pure helpers (`computeFieldDiff`, capability-summary, `ScriptContextKind`) live in `@checkstack/ai-common`.
10
+
11
+ Tools shipped:
12
+
13
+ - Health checks and automations: full CRUD - `healthcheck.propose` / `automation.propose` and `*.update` (`mutate`, deep-validated) and `*.delete` (`destructive`, always confirm-gated). `healthcheck.propose`'s dry-run calls the new deep `validateConfiguration` so propose-time validation matches apply-time. Assertions are validated against the collector's result schema and the canonical operator vocabulary. Capability-catalog tools (`ai.listCapabilities`, `ai.getCapabilitySchema`), script context tools (`ai.getScriptContext`, `ai.testScript`), and notify-subscriber tools (`healthcheck.notifySystemSubscribers` / `...GroupSubscribers`).
14
+ - Catalog: `catalog.createSystem` / `updateSystem` / `createGroup` / `updateGroup` (`mutate`), `catalog.deleteSystem` / `deleteGroup` (`destructive`), membership tools (`mutate`), plus `catalog.listSystems` / `listGroups` read projections.
15
+ - Incident: `incident.create` / `update` / `addUpdate` / `resolve` / `addLink` (`mutate`), `incident.delete` / `removeLink` (`destructive`), and `incident.get` / `incident.list` read projections.
16
+ - Maintenance: `maintenance.create` / `update` / `addUpdate` / `close` / `addLink` (`mutate`), `maintenance.delete` / `removeLink` (`destructive`), and `maintenance.list` / `get` read projections.
17
+ - Read projections for SLO (`slo.listObjectives`), dependency (`dependency.list`), incident (`incident.list`), healthcheck (`healthcheck.status`), and anomaly (`anomaly.explain`), each gated by the source procedure's own access rule and routed as the principal.
18
+ - Documentation grounding: `ai.searchDocs` / `ai.getDoc` over a build-time bundled docs index (BM25-ish ranking), so the assistant grounds how-to answers in Checkstack's own docs offline.
19
+ - URL introspection: `ai.probeUrl`, an SSRF-guarded read tool the assistant uses to inspect a real endpoint before drafting a health check. Update tools compute a before -> after field diff rendered on the confirm card (approve mode) or an "Applied" card (auto mode), so a change is never silent.
20
+
21
+ `ai_analyze` automation action (automation-backend, with an editor connection picker + audited tool calls): runs a bounded AI agent on the run context as the automation's `runAs` service account, so it can never exceed that identity's permissions; destructive tools are never offered; mutating tools auto-apply through the service account's client. Produces an `automation.analysis` artifact downstream actions can branch on. The agent loop is exposed as a headless `aiAgentRunnerRef` service so automation-backend can drive it without depending on ai-backend.
22
+
23
+ `notification.notifyForSubscription` is now callable by user / application principals holding `notification.send` (previously service-only). Every tool routes through the user-scoped client, so handler-side authorization is enforced exactly as a direct UI/RPC action; the resolver gate plus the propose/apply re-check at propose AND apply are the additional authority. A systemic authz regression test asserts every registered tool falls into exactly one safe authorization category.
24
+
25
+ A new `ai_transport` enum value `automation` records the AI action's tool calls in the `ai_tool_calls` audit log. No new durable state beyond that; each tool is a thin, deterministic wrapper over an existing RPC, so every pod behaves identically.
26
+
27
+ This is a beta minor.
28
+
29
+ - 9dcc848: Automations now run as a configured service account, removing implicit god-mode from the dispatch path.
30
+
31
+ BREAKING: every automation must declare a `runAs` application (service account). Previously every automation action ran as the trusted service client, bypassing all access-rule, per-resource, and team-scope checks - so an automation could touch any team's data. Now each automation runs as a bounded `application` principal, and every data-access call an action makes is authorized exactly as that identity. An automation with no `runAs` fails to run with a clear error rather than falling back to the trusted client; legacy automations must be assigned a service account before they run again.
32
+
33
+ What changed:
34
+
35
+ - New top-level field `runAs` on automations (a `run_as_application_id` column + create/update inputs; `AutomationSchema.runAs`). Required on create; GitOps sets it via the `run-as` metadata label.
36
+ - A new `coreServices.rpcClientAs(applicationId)` mints a short-lived, backend-signed app-principal token; the auth service resolves it LIVE to an `application` principal (reusing `enrichApplicationPrincipal`), so it flows through full `autoAuthMiddleware` enforcement. The dispatch engine threads this client into every action's `execute` as the required `context.rpcClient`.
37
+ - Bind authority (anti-escalation): a user may only bind an application whose access rules are a subset of their own (`isApplicationBindable`); `getBindableApplications` lists only bindable apps, and the create/update handlers enforce the check.
38
+ - `notification.sendTransactional` moves from service-only to access-gated (`notification.send`, a new access rule), so an automation's `runAs` can call the built-in `notify_user` / `notification.send` actions; trusted services still bypass via short-circuit.
39
+ - A "Run as (Service Account)" picker in the automation editor, populated from `getBindableApplications` (server-side filtered to bindable apps), seeding from the loaded `runAs` on edit and passing it into create + update. First-class teaching UX: an inline info banner, a blocked Save with an inline hint until one is chosen, and an empty state linking to the Applications admin + docs when none are bindable.
40
+
41
+ State and scale: `runAs` resolution is a pure read over shared tables; the app-principal token is self-contained and verified statelessly, so the per-run client is correct under horizontal scale.
42
+
43
+ This is a beta minor.
44
+
45
+ - 9dcc848: Align workspace dependency versions and migrate React Router to v7.
46
+
47
+ BREAKING CHANGES (React Router v7): All frontend packages now depend on `react-router-dom@^7.16.0`. Previously the workspace declared four divergent ranges (`^6.20.0`, `^6.22.0`, `^7.1.1`, `^7.14.2`), which resolved both `react-router@6` and `react-router@7` into a single bundle. Everything is now unified on v7. The public imports the app uses (`BrowserRouter`, `Routes`, `Route`, `Link`, `NavLink`, `MemoryRouter`, `useNavigate`, `useParams`, `useSearchParams`, `useLocation`) are unchanged between v6 and v7, so no source rewrites were required - but any out-of-tree plugin still on react-router v6 should upgrade to v7 (see the React Router v6 -> v7 upgrade guide) to share the host's single router instance via the import map.
48
+
49
+ Other unified ranges (no API change): `react` -> `^18.3.1`, the `@orpc/*` family (`contract`, `server`, `client`, `tanstack-query`, `openapi`, `zod`) -> `^1.14.4`, and `better-auth` -> `^1.6.13`.
50
+
51
+ Removed the pre-rename `@orpc/react-query` leftover from `@checkstack/frontend-api`; its `createRouterUtils` / `RouterUtils` / `ProcedureUtils` now come from `@orpc/tanstack-query` (the package already in use).
52
+
53
+ Stale in-range runtime deps pulled up to current published versions: `hono` `^4.12.23`, `@tanstack/react-query` (+devtools) `^5.100.14`, `date-fns` `^4.4.0`, `jose` `^6.2.3`, `tar` `^7.5.16`, `semver` `^7.8.1`, `@xyflow/react` `^12.11.0`.
54
+
55
+ ### Patch Changes
56
+
57
+ - Updated dependencies [9dcc848]
58
+ - Updated dependencies [9dcc848]
59
+ - Updated dependencies [9dcc848]
60
+ - Updated dependencies [9dcc848]
61
+ - @checkstack/common@0.13.0
62
+ - @checkstack/signal-common@0.2.6
63
+
3
64
  ## 1.2.1
4
65
 
5
66
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkstack/notification-common",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "license": "Elastic-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -10,15 +10,15 @@
10
10
  }
11
11
  },
12
12
  "dependencies": {
13
- "@checkstack/common": "0.11.0",
14
- "@checkstack/signal-common": "0.2.4",
15
- "@orpc/contract": "^1.13.14",
13
+ "@checkstack/common": "0.12.0",
14
+ "@checkstack/signal-common": "0.2.5",
15
+ "@orpc/contract": "^1.14.4",
16
16
  "zod": "^4.0.0"
17
17
  },
18
18
  "devDependencies": {
19
19
  "@checkstack/tsconfig": "0.0.7",
20
20
  "typescript": "^5.7.2",
21
- "@checkstack/scripts": "0.3.3"
21
+ "@checkstack/scripts": "0.3.4"
22
22
  },
23
23
  "scripts": {
24
24
  "typecheck": "tsgo -b",
package/src/access.ts CHANGED
@@ -12,9 +12,24 @@ export const notificationAccess = {
12
12
  "manage",
13
13
  "Configure notification settings and send broadcasts"
14
14
  ),
15
+ /**
16
+ * Send transactional notifications and notify subscribers. Granted to
17
+ * service-account identities (e.g. an automation's `runAs`) so they can
18
+ * call `sendTransactional` / `notifyForSubscription` without the broad
19
+ * `admin` capability. Trusted backend services bypass access checks and do
20
+ * not need this rule.
21
+ */
22
+ send: access(
23
+ "notification.send",
24
+ "manage",
25
+ "Send transactional notifications and notify subscribers"
26
+ ),
15
27
  };
16
28
 
17
29
  /**
18
30
  * All access rules for registration with the plugin system.
19
31
  */
20
- export const notificationAccessRules = [notificationAccess.admin];
32
+ export const notificationAccessRules = [
33
+ notificationAccess.admin,
34
+ notificationAccess.send,
35
+ ];
@@ -454,8 +454,8 @@ export const notificationContract = {
454
454
  */
455
455
  notifyForSubscription: proc({
456
456
  operationType: "mutation",
457
- userType: "service",
458
- access: [],
457
+ userType: "authenticated",
458
+ access: [notificationAccess.send],
459
459
  })
460
460
  .input(
461
461
  z.object({
@@ -472,11 +472,14 @@ export const notificationContract = {
472
472
  )
473
473
  .output(z.object({ notifiedCount: z.number() })),
474
474
 
475
- // Send transactional notification via ALL enabled strategies
475
+ // Send transactional notification via ALL enabled strategies.
476
+ // userType "authenticated" + access gate: trusted services bypass checks
477
+ // (short-circuit), while a service-account principal (e.g. an automation's
478
+ // `runAs`) must hold `notification.send`.
476
479
  sendTransactional: proc({
477
480
  operationType: "mutation",
478
- userType: "service",
479
- access: [],
481
+ userType: "authenticated",
482
+ access: [notificationAccess.send],
480
483
  })
481
484
  .input(
482
485
  z.object({