@automagik/omni 2.260914.12 → 2.260914.14

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.
@@ -0,0 +1,41 @@
1
+ -- Config-mutation audit log (issue #1152).
2
+ --
3
+ -- api_key_audit_logs records method/path/status only and is dominated by
4
+ -- polling GETs. tenant_audit_logs needs a tenant FK + credential uuid, so it
5
+ -- does not fit single-tenant legacy keys. This table holds one row per
6
+ -- POST/PATCH/PUT/DELETE on config resources (instances, agents, providers,
7
+ -- routes, automations, keys, settings) with actor, request id, client IP,
8
+ -- user agent, target, and before/after of changed fields. Secret-bearing
9
+ -- values are stored only as sha256 prefix fingerprints.
10
+ --
11
+ -- Retention: reads are never written here; keep ~180d.
12
+ --
13
+ -- Hand-written following the 0043/0044/0052 precedent (additive, idempotent).
14
+ -- No explicit BEGIN/COMMIT — the boot migrator executes this file on a pooled
15
+ -- postgres-js connection, which rejects raw transaction control.
16
+
17
+ CREATE TABLE IF NOT EXISTS "config_audit_logs" (
18
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
19
+ "api_key_id" varchar(100),
20
+ "api_key_name" varchar(255),
21
+ "actor" varchar(255),
22
+ "request_id" varchar(100),
23
+ "ip_address" varchar(64),
24
+ "user_agent" text,
25
+ "method" varchar(10) NOT NULL,
26
+ "path" varchar(500) NOT NULL,
27
+ "status_code" integer NOT NULL,
28
+ "action" varchar(100) NOT NULL,
29
+ "target_type" varchar(50) NOT NULL,
30
+ "target_id" varchar(255),
31
+ "changed_fields" text[] DEFAULT '{}'::text[] NOT NULL,
32
+ "changes" jsonb DEFAULT '{}'::jsonb NOT NULL,
33
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
34
+ );
35
+
36
+ CREATE INDEX IF NOT EXISTS "config_audit_logs_target_idx"
37
+ ON "config_audit_logs" ("target_type", "target_id");
38
+ CREATE INDEX IF NOT EXISTS "config_audit_logs_actor_idx"
39
+ ON "config_audit_logs" ("actor");
40
+ CREATE INDEX IF NOT EXISTS "config_audit_logs_created_at_idx"
41
+ ON "config_audit_logs" ("created_at");
@@ -491,6 +491,13 @@
491
491
  "when": 1786900000000,
492
492
  "tag": "0069_automation_allow_instance_senders",
493
493
  "breakpoints": true
494
+ },
495
+ {
496
+ "idx": 70,
497
+ "version": "7",
498
+ "when": 1787000000000,
499
+ "tag": "0070_config_audit_logs",
500
+ "breakpoints": true
494
501
  }
495
502
  ]
496
503
  }
package/dist/client.d.ts CHANGED
@@ -24,4 +24,12 @@ export declare function getClient(): OmniClient;
24
24
  * Returns null if not authenticated.
25
25
  */
26
26
  export declare function getOptionalClient(): OmniClient | null;
27
+ /**
28
+ * Tag every request to the configured Omni server with `X-Omni-Actor` from
29
+ * `OMNI_ACTOR` (e.g. `claude-session:<id>`, `cli:alice`) so the config audit
30
+ * log (#1152) can tell agents and humans apart. Wraps global fetch because many
31
+ * commands call the API directly instead of through the SDK; requests to any
32
+ * other host are left untouched.
33
+ */
34
+ export declare function installActorHeader(): void;
27
35
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAoB,MAAM,WAAW,CAAC;AAW9D;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,IAAI,KAAK,CAQ5C;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,UAAU,CAyBtC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,UAAU,GAAG,IAAI,CAyBrD"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAoB,MAAM,WAAW,CAAC;AAW9D;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,IAAI,KAAK,CAQ5C;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,UAAU,CAyBtC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,UAAU,GAAG,IAAI,CAyBrD;AA2BD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAazC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Audit Commands (issue #1152)
3
+ *
4
+ * omni audit list [--target <id>] [--type <type>] [--actor <x>] [--since <iso>] [--limit <n>]
5
+ * omni audit show <id>
6
+ *
7
+ * Reads the config-mutation audit log. Set OMNI_ACTOR to tag your own calls.
8
+ */
9
+ import { Command } from 'commander';
10
+ export declare function createAuditCommand(): Command;
11
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6BpC,wBAAgB,kBAAkB,IAAI,OAAO,CAyC5C"}
package/dist/index.js CHANGED
@@ -81874,6 +81874,7 @@ __export(exports_schema, {
81874
81874
  connectorWindowSemanticsValues: () => connectorWindowSemanticsValues,
81875
81875
  connectorMutationPolicies: () => connectorMutationPolicies,
81876
81876
  connectorLivenessStatuses: () => connectorLivenessStatuses,
81877
+ configAuditLogs: () => configAuditLogs,
81877
81878
  conditionOperators: () => conditionOperators,
81878
81879
  closeContactOutcomes: () => closeContactOutcomes,
81879
81880
  closeContactLogs: () => closeContactLogs,
@@ -81922,7 +81923,7 @@ __export(exports_schema, {
81922
81923
  accessRules: () => accessRules,
81923
81924
  accessModes: () => accessModes
81924
81925
  });
81925
- var channelTypes, agentTypes, agentSystems, agentEntityTypes, debounceMode, splitDelayMode, supersedeMode, replyFilterMode, agentSessionStrategies, ruleTypes, accessModes, settingValueTypes, apiKeyStatuses, apiKeyProfiles, eventTypes, contentTypes, chatTypes, messageSources, messageTypes, messageStatuses, deliveryStatuses, scheduledMessageDeliveryModes, scheduledMessageStatuses, jobStatuses, providerSchemas, agentProviders, agents, agentRoutes, agentSessions, apiKeys, apiKeyAuditLogs, apiKeysRelations, apiKeyAuditLogsRelations, instances, whatsappTemplates, whatsappFlowKeys, scheduledMessages, persons, platformIdentities, conversations, chats, chatParticipants, omniGroups, messages2, omniEvents, handoffLogs, closeContactOutcomes, closeContactLogs, accessRules, globalSettings, settingChangeHistory, batchJobs, syncJobTypes, syncJobs, mediaContent, chatIdMappings, pluginStorage, agentProvidersRelations, agentsRelations, instancesRelations, syncJobsRelations, personsRelations, platformIdentitiesRelations, conversationsRelations, chatsRelations, chatParticipantsRelations, messagesRelations, omniEventsRelations, accessRulesRelations, globalSettingsRelations, settingChangeHistoryRelations, batchJobsRelations, mediaContentRelations, chatIdMappingsRelations, deadLetterStatuses, deadLetterEvents, payloadStorageConfig, payloadStages, eventPayloads, webhookSignatureAlgorithms, connectorLivenessStatuses, connectorWindowSemanticsValues, connectorMutationPolicies, webhookSources, eventSchemas, conditionOperators, actionTypes, automationDebounceModes, automations2, automationLogStatuses, automationLogs, consumerOffsets, durableConsumers, automationsRelations, automationLogsRelations, triggerLogs, triggerLogsRelations, agentRoutesRelations, agentTaskStatuses, agentTasks, agentTasksRelations, turnStatuses, turnActions, turns, turnsRelations, followUpDisarmReasons, chatFollowUpState, chatFollowUpStateRelations, processedEvents, genieHosts, tenantStatuses, principalTypes, principalStatuses, tenantRoles, membershipStatuses, credentialClasses, authCredentialStatuses, platformApiKeyStatuses, tenants, principals, tenantMemberships, tenantRolePolicies, platformApiKeys, tenantKeyLineage, authCredentials, tenantAuditLogs, platformAuditLogs, platformProviderCatalog, tenantProviderConfig, platformSettings, tenantSettings, platformSettingChangeHistory, tenantSettingChangeHistory, platformPluginStorage, tenantPluginStorage, platformPayloadStorageConfig, tenantPayloadStorageOverrides, tenantMigrationLedger, tenantMigrationLedgerHistory;
81926
+ var channelTypes, agentTypes, agentSystems, agentEntityTypes, debounceMode, splitDelayMode, supersedeMode, replyFilterMode, agentSessionStrategies, ruleTypes, accessModes, settingValueTypes, apiKeyStatuses, apiKeyProfiles, eventTypes, contentTypes, chatTypes, messageSources, messageTypes, messageStatuses, deliveryStatuses, scheduledMessageDeliveryModes, scheduledMessageStatuses, jobStatuses, providerSchemas, agentProviders, agents, agentRoutes, agentSessions, apiKeys, apiKeyAuditLogs, apiKeysRelations, apiKeyAuditLogsRelations, instances, whatsappTemplates, whatsappFlowKeys, scheduledMessages, persons, platformIdentities, conversations, chats, chatParticipants, omniGroups, messages2, omniEvents, handoffLogs, closeContactOutcomes, closeContactLogs, accessRules, globalSettings, settingChangeHistory, batchJobs, syncJobTypes, syncJobs, mediaContent, chatIdMappings, pluginStorage, agentProvidersRelations, agentsRelations, instancesRelations, syncJobsRelations, personsRelations, platformIdentitiesRelations, conversationsRelations, chatsRelations, chatParticipantsRelations, messagesRelations, omniEventsRelations, accessRulesRelations, globalSettingsRelations, settingChangeHistoryRelations, batchJobsRelations, mediaContentRelations, chatIdMappingsRelations, deadLetterStatuses, deadLetterEvents, payloadStorageConfig, payloadStages, eventPayloads, webhookSignatureAlgorithms, connectorLivenessStatuses, connectorWindowSemanticsValues, connectorMutationPolicies, webhookSources, eventSchemas, conditionOperators, actionTypes, automationDebounceModes, automations2, automationLogStatuses, automationLogs, consumerOffsets, durableConsumers, automationsRelations, automationLogsRelations, triggerLogs, triggerLogsRelations, agentRoutesRelations, agentTaskStatuses, agentTasks, agentTasksRelations, turnStatuses, turnActions, turns, turnsRelations, followUpDisarmReasons, chatFollowUpState, chatFollowUpStateRelations, processedEvents, genieHosts, tenantStatuses, principalTypes, principalStatuses, tenantRoles, membershipStatuses, credentialClasses, authCredentialStatuses, platformApiKeyStatuses, tenants, principals, tenantMemberships, tenantRolePolicies, platformApiKeys, tenantKeyLineage, authCredentials, tenantAuditLogs, platformAuditLogs, platformProviderCatalog, tenantProviderConfig, platformSettings, tenantSettings, platformSettingChangeHistory, tenantSettingChangeHistory, platformPluginStorage, tenantPluginStorage, platformPayloadStorageConfig, tenantPayloadStorageOverrides, tenantMigrationLedger, tenantMigrationLedgerHistory, configAuditLogs;
81926
81927
  var init_schema2 = __esm(() => {
81927
81928
  init_events();
81928
81929
  init_types4();
@@ -83995,6 +83996,28 @@ var init_schema2 = __esm(() => {
83995
83996
  revisionUq: uniqueIndex("tenant_migration_ledger_history_revision_uq").on(table3.ledgerId, table3.revision),
83996
83997
  ledgerIdx: index("tenant_migration_ledger_history_ledger_idx").on(table3.ledgerId)
83997
83998
  }));
83999
+ configAuditLogs = pgTable("config_audit_logs", {
84000
+ id: uuid("id").primaryKey().defaultRandom(),
84001
+ apiKeyId: varchar("api_key_id", { length: 100 }),
84002
+ apiKeyName: varchar("api_key_name", { length: 255 }),
84003
+ actor: varchar("actor", { length: 255 }),
84004
+ requestId: varchar("request_id", { length: 100 }),
84005
+ ipAddress: varchar("ip_address", { length: 64 }),
84006
+ userAgent: text("user_agent"),
84007
+ method: varchar("method", { length: 10 }).notNull(),
84008
+ path: varchar("path", { length: 500 }).notNull(),
84009
+ statusCode: integer("status_code").notNull(),
84010
+ action: varchar("action", { length: 100 }).notNull(),
84011
+ targetType: varchar("target_type", { length: 50 }).notNull(),
84012
+ targetId: varchar("target_id", { length: 255 }),
84013
+ changedFields: text("changed_fields").array().notNull().default(sql`'{}'::text[]`),
84014
+ changes: jsonb("changes").$type().notNull().default({}),
84015
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
84016
+ }, (table3) => ({
84017
+ targetIdx: index("config_audit_logs_target_idx").on(table3.targetType, table3.targetId),
84018
+ actorIdx: index("config_audit_logs_actor_idx").on(table3.actor),
84019
+ createdAtIdx: index("config_audit_logs_created_at_idx").on(table3.createdAt)
84020
+ }));
83998
84021
  });
83999
84022
 
84000
84023
  // ../../node_modules/.bun/drizzle-orm@0.45.2+803b5ba9c660628f/node_modules/drizzle-orm/cache/core/index.js
@@ -137266,7 +137289,7 @@ import { fileURLToPath } from "url";
137266
137289
  // package.json
137267
137290
  var package_default = {
137268
137291
  name: "@automagik/omni",
137269
- version: "2.260914.12",
137292
+ version: "2.260914.14",
137270
137293
  repository: {
137271
137294
  type: "git",
137272
137295
  url: "git+https://github.com/automagik-dev/omni.git",
@@ -137508,6 +137531,22 @@ function signRequestIfHandshook(baseUrl) {
137508
137531
  const bound = ctx;
137509
137532
  return (method, path, body) => bound.signRequest(method, path, body);
137510
137533
  }
137534
+ function installActorHeader() {
137535
+ const actor = process.env.OMNI_ACTOR?.trim();
137536
+ if (!actor)
137537
+ return;
137538
+ const original = globalThis.fetch;
137539
+ const wrapped = (input, init) => {
137540
+ const url = input instanceof Request ? input.url : String(input);
137541
+ const base = (loadConfig().apiUrl ?? DEFAULT_API_URL2).replace(/\/$/, "");
137542
+ if (!url.startsWith(base))
137543
+ return original(input, init);
137544
+ const headers = new Headers(init?.headers ?? (input instanceof Request ? input.headers : undefined));
137545
+ headers.set("x-omni-actor", actor);
137546
+ return original(input, { ...init, headers });
137547
+ };
137548
+ globalThis.fetch = Object.assign(wrapped, original);
137549
+ }
137511
137550
 
137512
137551
  // src/commands/a2a.ts
137513
137552
  init_output();
@@ -138615,6 +138654,50 @@ function createAgentsCommand() {
138615
138654
  return agents;
138616
138655
  }
138617
138656
 
138657
+ // src/commands/audit.ts
138658
+ init_config();
138659
+ init_output();
138660
+ async function auditFetch(path) {
138661
+ if (!hasAuth())
138662
+ exitNotAuthenticated();
138663
+ const config2 = loadConfig();
138664
+ const res = await fetch(`${config2.apiUrl ?? "http://localhost:8882"}/api/v2/audit${path}`, {
138665
+ headers: { "x-api-key": config2.apiKey ?? "" }
138666
+ });
138667
+ if (!res.ok)
138668
+ error(`Audit request failed: HTTP ${res.status} ${await res.text().catch(() => "")}`);
138669
+ return await res.json();
138670
+ }
138671
+ function createAuditCommand() {
138672
+ const audit = new Command("audit").description("Config-mutation audit log (who changed what)");
138673
+ audit.command("list").description("List config changes, newest first").option("--target <id>", "Filter by target id (instance, agent, provider, ...)").option("--type <type>", "Filter by target type (instance|agent|provider|route|automation|api_key|setting)").option("--actor <actor>", "Filter by X-Omni-Actor or API key name").option("--since <iso>", "Only changes at or after this timestamp").option("--limit <n>", "Max results", "50").action(async (opts) => {
138674
+ const params = new URLSearchParams({ limit: opts.limit });
138675
+ if (opts.target)
138676
+ params.set("target", opts.target);
138677
+ if (opts.type)
138678
+ params.set("targetType", opts.type);
138679
+ if (opts.actor)
138680
+ params.set("actor", opts.actor);
138681
+ if (opts.since)
138682
+ params.set("since", opts.since);
138683
+ const { items } = await auditFetch(`?${params}`);
138684
+ list(items.map((e10) => ({
138685
+ id: e10.id,
138686
+ time: e10.createdAt,
138687
+ actor: e10.actor ?? e10.apiKeyName ?? "-",
138688
+ action: e10.action,
138689
+ target: e10.targetId ?? "-",
138690
+ status: e10.statusCode,
138691
+ changed: e10.changedFields.join(", ") || "-"
138692
+ })), { emptyMessage: "No audit entries.", rawData: items });
138693
+ });
138694
+ audit.command("show <id>").description("Show one audit entry with before/after (secrets as fingerprints)").action(async (id) => {
138695
+ const { data: data2 } = await auditFetch(`/${encodeURIComponent(id)}`);
138696
+ data(data2);
138697
+ });
138698
+ return audit;
138699
+ }
138700
+
138618
138701
  // src/commands/auth.ts
138619
138702
  init_config();
138620
138703
 
@@ -153996,6 +154079,12 @@ var COMMANDS = [
153996
154079
  helpGroup: "Management",
153997
154080
  helpDescription: "Agent routing configuration"
153998
154081
  },
154082
+ {
154083
+ create: createAuditCommand,
154084
+ category: "core",
154085
+ helpGroup: "Management",
154086
+ helpDescription: "Config-mutation audit log"
154087
+ },
153999
154088
  {
154000
154089
  create: createKeysCommand,
154001
154090
  category: "core",
@@ -154303,6 +154392,7 @@ program2.configureOutput({
154303
154392
  }
154304
154393
  });
154305
154394
  selfHealManifestPin();
154395
+ installActorHeader();
154306
154396
  var argv = process.argv.slice(2);
154307
154397
  var isRootVersionOnly = argv.length > 0 && argv.every((arg) => arg === "--version" || arg === "-V");
154308
154398
  if (isRootVersionOnly) {