doover-js 0.6.0 → 0.6.1

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/dist/index.d.ts CHANGED
@@ -47,4 +47,6 @@ export type * from "./types/common";
47
47
  export type * from "./types/connection";
48
48
  export type * from "./types/openapi";
49
49
  export type * from "./types/viewer";
50
+ export type * from "./types/audit";
51
+ export { DV_AUDIT_CHANNEL } from "./types/audit";
50
52
  export { addTimestampToMessage, extractSnowflakeId, generateSnowflakeIdAtTime, } from "./utils/snowflake";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateSnowflakeIdAtTime = exports.extractSnowflakeId = exports.addTimestampToMessage = exports.getIdentifierFromPath = exports.DooverDataProvider = exports.DooverValidationError = exports.DooverGatewayError = exports.DooverApiError = exports.RestClient = exports.GatewayClient = exports.buildAuth = exports.DooverAuthError = exports.AuthProfile = exports.DooverTokenAuth = exports.CookieAuth = exports.DooverAuth = exports.AmbiguousWriteError = exports.UnsupportedCapabilityError = exports.ALL_CAPABILITIES = exports.DooverRpcError = exports.RpcDispatcher = exports.UsersApi = exports.TurnApi = exports.ProcessorsApi = exports.PermissionsApi = exports.NotificationsApi = exports.MessagesApi = exports.ConnectionsApi = exports.ChannelsApi = exports.AlarmsApi = exports.AggregatesApi = exports.AgentsApi = exports.DooverStatsCollector = exports.resetDooverClient = exports.peekDooverClient = exports.getDooverClient = exports.MultiplexClient = exports.LocalAgentClient = exports.DooverClient = void 0;
3
+ exports.generateSnowflakeIdAtTime = exports.extractSnowflakeId = exports.addTimestampToMessage = exports.DV_AUDIT_CHANNEL = exports.getIdentifierFromPath = exports.DooverDataProvider = exports.DooverValidationError = exports.DooverGatewayError = exports.DooverApiError = exports.RestClient = exports.GatewayClient = exports.buildAuth = exports.DooverAuthError = exports.AuthProfile = exports.DooverTokenAuth = exports.CookieAuth = exports.DooverAuth = exports.AmbiguousWriteError = exports.UnsupportedCapabilityError = exports.ALL_CAPABILITIES = exports.DooverRpcError = exports.RpcDispatcher = exports.UsersApi = exports.TurnApi = exports.ProcessorsApi = exports.PermissionsApi = exports.NotificationsApi = exports.MessagesApi = exports.ConnectionsApi = exports.ChannelsApi = exports.AlarmsApi = exports.AggregatesApi = exports.AgentsApi = exports.DooverStatsCollector = exports.resetDooverClient = exports.peekDooverClient = exports.getDooverClient = exports.MultiplexClient = exports.LocalAgentClient = exports.DooverClient = void 0;
4
4
  var doover_client_1 = require("./client/doover-client");
5
5
  Object.defineProperty(exports, "DooverClient", { enumerable: true, get: function () { return doover_client_1.DooverClient; } });
6
6
  var local_agent_client_1 = require("./client/local-agent-client");
@@ -68,6 +68,8 @@ var doover_data_provider_1 = require("./viewer/doover-data-provider");
68
68
  Object.defineProperty(exports, "DooverDataProvider", { enumerable: true, get: function () { return doover_data_provider_1.DooverDataProvider; } });
69
69
  var path_parsing_1 = require("./viewer/path-parsing");
70
70
  Object.defineProperty(exports, "getIdentifierFromPath", { enumerable: true, get: function () { return path_parsing_1.getIdentifierFromPath; } });
71
+ var audit_1 = require("./types/audit");
72
+ Object.defineProperty(exports, "DV_AUDIT_CHANNEL", { enumerable: true, get: function () { return audit_1.DV_AUDIT_CHANNEL; } });
71
73
  var snowflake_1 = require("./utils/snowflake");
72
74
  Object.defineProperty(exports, "addTimestampToMessage", { enumerable: true, get: function () { return snowflake_1.addTimestampToMessage; } });
73
75
  Object.defineProperty(exports, "extractSnowflakeId", { enumerable: true, get: function () { return snowflake_1.extractSnowflakeId; } });
@@ -1,6 +1,9 @@
1
1
  import { type InfiniteData, type UseInfiniteQueryResult } from "@tanstack/react-query";
2
2
  import type { MessageStructure } from "../types/common";
3
- export declare function multiAgentChannelMessagesQueryKey(channelName: string, agentIds: string[], sources?: string[]): readonly ["doover", "channel", string, "messages", string, "src", string];
3
+ export declare function multiAgentChannelMessagesQueryKey(channelName: string, agentIds: string[], sources?: string[], scope?: {
4
+ after?: string;
5
+ fields?: readonly string[];
6
+ }): readonly ["doover", "channel", string, "messages", string, "src", string] | readonly ["doover", "channel", string, "messages", string, "src", string, Record<string, unknown>];
4
7
  export interface UseMultiAgentChannelMessagesOptions {
5
8
  limit?: number;
6
9
  /** If false, skip live subscriptions per agent. Defaults true. */
@@ -12,6 +15,14 @@ export interface UseMultiAgentChannelMessagesOptions {
12
15
  fields?: string[];
13
16
  /** Optional first-page `before` cursor (snowflake id). */
14
17
  initialBefore?: string;
18
+ /**
19
+ * Optional lower-bound snowflake id. Forwarded server-side so each
20
+ * agent's pagination stops on its own once it walks past the bound —
21
+ * mirrors `useChannelMessages`'s `after`. Use this to fetch a bounded
22
+ * time window (e.g. last 24h) across many agents without filtering
23
+ * on the client.
24
+ */
25
+ after?: string;
15
26
  /**
16
27
  * Restrict to these source ids on a `MultiplexClient`. Ignored for a plain
17
28
  * `DooverClient` or `LocalAgentClient`. When set, the query key is
@@ -5,9 +5,9 @@ exports.useMultiAgentChannelMessages = useMultiAgentChannelMessages;
5
5
  const react_1 = require("react");
6
6
  const react_query_1 = require("@tanstack/react-query");
7
7
  const context_1 = require("./context");
8
- function multiAgentChannelMessagesQueryKey(channelName, agentIds, sources) {
8
+ function multiAgentChannelMessagesQueryKey(channelName, agentIds, sources, scope) {
9
9
  const sourceDim = sources && sources.length ? [...sources].sort().join(",") : "*";
10
- return [
10
+ const base = [
11
11
  "doover",
12
12
  "channel",
13
13
  channelName,
@@ -16,6 +16,19 @@ function multiAgentChannelMessagesQueryKey(channelName, agentIds, sources) {
16
16
  "src",
17
17
  sourceDim,
18
18
  ];
19
+ // Pagination cursors come from the first page's response and are scoped
20
+ // to *that* response's `after`/`fields`. Mixing them under one cache
21
+ // entry would cause `getNextPageParam` to anchor on an unrelated page,
22
+ // so a differently-bounded request must live under its own key.
23
+ const scopeKey = {};
24
+ if (scope?.after)
25
+ scopeKey.after = scope.after;
26
+ if (scope?.fields && scope.fields.length > 0) {
27
+ scopeKey.fields = [...scope.fields].sort();
28
+ }
29
+ return Object.keys(scopeKey).length > 0
30
+ ? [...base, scopeKey]
31
+ : base;
19
32
  }
20
33
  function useMultiAgentChannelMessages(channelName, agentIds, options) {
21
34
  const client = (0, context_1.useDooverClient)();
@@ -25,7 +38,11 @@ function useMultiAgentChannelMessages(channelName, agentIds, options) {
25
38
  const fields = options?.fields;
26
39
  const initialBefore = options?.initialBefore;
27
40
  const sources = options?.sources;
28
- const key = multiAgentChannelMessagesQueryKey(channelName, agentIds, sources);
41
+ const after = options?.after;
42
+ const key = multiAgentChannelMessagesQueryKey(channelName, agentIds, sources, {
43
+ after,
44
+ fields,
45
+ });
29
46
  const prependMessage = (0, react_1.useCallback)((message) => {
30
47
  queryClient.setQueryData(key, (current) => {
31
48
  if (!current)
@@ -72,6 +89,7 @@ function useMultiAgentChannelMessages(channelName, agentIds, options) {
72
89
  ...(typeof pageParam === "string" ? { before: pageParam } : {}),
73
90
  ...(limit !== undefined ? { limit } : {}),
74
91
  ...(fields && fields.length > 0 ? { field_name: fields } : {}),
92
+ ...(after !== undefined ? { after } : {}),
75
93
  };
76
94
  // Pass `{ sources }` as a trailing bag only when set — cast through
77
95
  // `never` since the TypeScript overloads don't declare it.
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Audit event types — mirror of the records doover-control writes to the
3
+ * `dv-audit` channel (see ``doover-control/doover_control/events/audit.py``
4
+ * for the source of truth).
5
+ *
6
+ * Each record is read back via the standard channel-messages APIs: it lands
7
+ * inside a ``MessageStructure<AuditEvent>`` envelope (with ``id``, ``timestamp``,
8
+ * ``channel``, etc.), and the record itself is on ``message.data``.
9
+ */
10
+ /** Channel name on which audit records live in doover-data. */
11
+ export declare const DV_AUDIT_CHANNEL = "dv-audit";
12
+ /** The role this party plays in the record. */
13
+ export type AuditEntityType = "device" | "user" | "organisation" | "Tunnel" | "ApplicationInstallation" | "SolutionInstallation" | "ApplicationDeployment" | "ObjectGroup" | "PendingUser" | "User" | "fusionauth" | "system";
14
+ export interface AuditEntity {
15
+ type: AuditEntityType;
16
+ /** Stringified id (User pk, Device pk, FA UUID, etc.). May be absent for `system`. */
17
+ id?: string;
18
+ /** Display name. May be an email for users / pending invites. */
19
+ name?: string;
20
+ }
21
+ export interface AuditOrganisation {
22
+ id: string;
23
+ name: string;
24
+ }
25
+ export interface AuditRequestContext {
26
+ ip_address?: string;
27
+ user_agent?: string;
28
+ }
29
+ /** Origin system for the event. */
30
+ export type AuditSource = "control" | "fusionauth" | "data" | "tunnels";
31
+ /**
32
+ * String-literal union of every wired audit action — kept in lock-step with
33
+ * ``doover_control/events/types.py``'s ``EventType`` enum. Future event types
34
+ * declared in Python but not yet emitted are intentionally included so the
35
+ * frontend mapping (icons, labels) can be filled in ahead of the wire-up.
36
+ */
37
+ export type AuditAction = "user.logged_in" | "user.login.failed" | "user.signed_up" | "user.created" | "user.updated" | "user.deleted" | "user.deactivated" | "user.reactivated" | "user.password_changed" | "user.password_reset" | "user.password_breached" | "user.mfa_changed" | "user.email_verified" | "user.email_changed" | "user.idp_linked" | "user.idp_unlinked" | "user.token_revoked" | "user.invited" | "user.removed" | "user.role_changed" | "app.installed" | "app.deployed" | "app.config_changed" | "app.uninstalled" | "solution.config_changed" | "group.created" | "group.edited" | "group.deleted" | "device.created" | "device.updated" | "device.config_changed" | "device.archived" | "device.unarchived" | "device.deleted" | "device.opened" | "tunnel.created" | "tunnel.deleted" | "tunnel.opened" | "tunnel.closed" | "tunnel.accessed" | "notification.sent" | "report.created" | "command.received";
38
+ /**
39
+ * The audit record payload as written by ``publish_audit`` — i.e. what you
40
+ * find on ``MessageStructure<AuditEvent>.data`` after reading the channel.
41
+ *
42
+ * The doover-data ``MessageStructure`` envelope provides ``id`` (snowflake)
43
+ * and ``timestamp`` (epoch ms) for ordering; this struct is the body only.
44
+ */
45
+ export interface AuditEvent {
46
+ action: AuditAction;
47
+ actor: AuditEntity | null;
48
+ subject: AuditEntity | null;
49
+ organisation: AuditOrganisation | null;
50
+ source: AuditSource;
51
+ metadata: Record<string, unknown>;
52
+ request_context: AuditRequestContext | null;
53
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ /**
3
+ * Audit event types — mirror of the records doover-control writes to the
4
+ * `dv-audit` channel (see ``doover-control/doover_control/events/audit.py``
5
+ * for the source of truth).
6
+ *
7
+ * Each record is read back via the standard channel-messages APIs: it lands
8
+ * inside a ``MessageStructure<AuditEvent>`` envelope (with ``id``, ``timestamp``,
9
+ * ``channel``, etc.), and the record itself is on ``message.data``.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.DV_AUDIT_CHANNEL = void 0;
13
+ /** Channel name on which audit records live in doover-data. */
14
+ exports.DV_AUDIT_CHANNEL = "dv-audit";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doover-js",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "TypeScript client for Doover.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",