@every-app/sdk 0.3.0-rc.1 → 0.3.0-rc.3
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/LICENSE +21 -0
- package/dist/cloudflare/index.d.ts +2 -2
- package/dist/cloudflare/index.d.ts.map +1 -1
- package/dist/cloudflare/index.js +1 -1
- package/dist/cloudflare/sentinel.d.ts +39 -1
- package/dist/cloudflare/sentinel.d.ts.map +1 -1
- package/dist/cloudflare/sentinel.js +22 -1
- package/dist/cloudflare/worker.d.ts +205 -7
- package/dist/cloudflare/worker.d.ts.map +1 -1
- package/dist/cloudflare/worker.js +174 -11
- package/dist/internal/aiDefault.d.ts +141 -0
- package/dist/internal/aiDefault.d.ts.map +1 -0
- package/dist/internal/aiDefault.js +204 -0
- package/dist/internal/aiProviders.d.ts +4 -1
- package/dist/internal/aiProviders.d.ts.map +1 -1
- package/dist/internal/aiProviders.js +5 -1
- package/dist/internal/appSettings.d.ts +20 -2
- package/dist/internal/appSettings.d.ts.map +1 -1
- package/dist/internal/appSettings.js +53 -7
- package/dist/internal/audit.d.ts +108 -0
- package/dist/internal/audit.d.ts.map +1 -0
- package/dist/internal/audit.js +235 -0
- package/dist/internal/capabilities.d.ts +2315 -141
- package/dist/internal/capabilities.d.ts.map +1 -1
- package/dist/internal/capabilities.js +122 -0
- package/dist/internal/catalog/commerce.d.ts +394 -0
- package/dist/internal/catalog/commerce.d.ts.map +1 -0
- package/dist/internal/catalog/commerce.js +477 -0
- package/dist/internal/catalog/comms.d.ts +338 -0
- package/dist/internal/catalog/comms.d.ts.map +1 -0
- package/dist/internal/catalog/comms.js +477 -0
- package/dist/internal/catalog/index.d.ts +1936 -0
- package/dist/internal/catalog/index.d.ts.map +1 -0
- package/dist/internal/catalog/index.js +19 -0
- package/dist/internal/catalog/inference.d.ts +393 -0
- package/dist/internal/catalog/inference.d.ts.map +1 -0
- package/dist/internal/catalog/inference.js +457 -0
- package/dist/internal/catalog/infra.d.ts +423 -0
- package/dist/internal/catalog/infra.d.ts.map +1 -0
- package/dist/internal/catalog/infra.js +543 -0
- package/dist/internal/catalog/search.d.ts +400 -0
- package/dist/internal/catalog/search.d.ts.map +1 -0
- package/dist/internal/catalog/search.js +463 -0
- package/dist/internal/devProviders.d.ts +2 -2
- package/dist/internal/devProviders.d.ts.map +1 -1
- package/dist/internal/devProviders.js +19 -1
- package/dist/internal/events.d.ts +13 -2
- package/dist/internal/events.d.ts.map +1 -1
- package/dist/internal/events.js +21 -3
- package/dist/internal/gatewaySettings.d.ts +2 -1
- package/dist/internal/gatewaySettings.d.ts.map +1 -1
- package/dist/internal/gatewaySettings.js +10 -2
- package/dist/internal/index.d.ts +5 -0
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +5 -0
- package/dist/internal/oauthPresets.d.ts +29 -0
- package/dist/internal/oauthPresets.d.ts.map +1 -0
- package/dist/internal/oauthPresets.js +534 -0
- package/dist/internal/oauthScopes.d.ts +56 -1
- package/dist/internal/oauthScopes.d.ts.map +1 -1
- package/dist/internal/oauthScopes.js +98 -4
- package/dist/internal/oauthSpec.d.ts +59 -0
- package/dist/internal/oauthSpec.d.ts.map +1 -0
- package/dist/internal/oauthSpec.js +676 -0
- package/dist/internal/protocol.d.ts +11 -0
- package/dist/internal/protocol.d.ts.map +1 -1
- package/dist/internal/protocol.js +9 -0
- package/dist/internal/providerRegistry.d.ts +17 -6
- package/dist/internal/providerRegistry.d.ts.map +1 -1
- package/dist/internal/providerRegistry.js +51 -2
- package/dist/internal/providerSpec.d.ts +11 -7
- package/dist/internal/providerSpec.d.ts.map +1 -1
- package/dist/internal/providerSpec.js +142 -33
- package/dist/internal/signInProviders.d.ts +104 -0
- package/dist/internal/signInProviders.d.ts.map +1 -0
- package/dist/internal/signInProviders.js +245 -0
- package/dist/server/ai.d.ts +45 -0
- package/dist/server/ai.d.ts.map +1 -0
- package/dist/server/ai.js +40 -0
- package/dist/server/connectUrl.d.ts +21 -0
- package/dist/server/connectUrl.d.ts.map +1 -0
- package/dist/server/connectUrl.js +37 -0
- package/dist/server/gatewayFetch.d.ts.map +1 -1
- package/dist/server/gatewayFetch.js +72 -8
- package/dist/server/index.d.ts +4 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -1
- package/dist/server/integrationFetch.d.ts +39 -2
- package/dist/server/integrationFetch.d.ts.map +1 -1
- package/dist/server/integrationFetch.js +177 -13
- package/package.json +12 -12
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
* the app Worker's secret names.
|
|
24
24
|
*/
|
|
25
25
|
import { type ApiKeyCapability, type CapabilityLookup } from "./capabilities.js";
|
|
26
|
+
import { type AiDefaultChoice, type IsSet } from "./aiDefault.js";
|
|
26
27
|
/** A provider as `providers` lists it: its id, or an entry with a need. */
|
|
27
28
|
export interface ProviderEntry extends SettingNeedFields {
|
|
28
29
|
id: string;
|
|
@@ -62,12 +63,16 @@ export interface SettingsManifestLike {
|
|
|
62
63
|
readonly secrets?: ReadonlyArray<string | SecretEntry>;
|
|
63
64
|
readonly ai?: {
|
|
64
65
|
readonly routes?: readonly string[];
|
|
66
|
+
/** The app needs the Gateway's default chat model (`/api/ai/default`): `true`, or an entry with its need. */
|
|
67
|
+
readonly chat?: boolean | SettingNeedFields;
|
|
65
68
|
};
|
|
66
69
|
/** A remote MCP app's registration (./remoteMcp.ts): its credential is a required Gateway setting. */
|
|
67
70
|
readonly remote?: unknown;
|
|
68
71
|
readonly name?: string;
|
|
69
72
|
}
|
|
70
73
|
export type SettingKind = "provider" | "capability" | "secret" | "ai-routes"
|
|
74
|
+
/** The Gateway's default model provider (`ai.chat`): one key of any provider in the order, or the operator's choice. */
|
|
75
|
+
| "ai-default"
|
|
71
76
|
/** A remote MCP app's credential (./remoteMcp.ts): one Gateway setting named by the row. */
|
|
72
77
|
| "remote-mcp";
|
|
73
78
|
/** Which Worker holds a setting: the Gateway's, or the app's own. */
|
|
@@ -80,6 +85,13 @@ export type SettingNeed = {
|
|
|
80
85
|
kind: "anyOf";
|
|
81
86
|
group: string;
|
|
82
87
|
};
|
|
88
|
+
/** What `appSettings` may be told about the Gateway, for the default model provider. */
|
|
89
|
+
export interface AppSettingsOptions {
|
|
90
|
+
/** The operator's stored default (`everyapp ai default`), or none. */
|
|
91
|
+
aiDefault?: AiDefaultChoice | null;
|
|
92
|
+
/** What is set, to put the configured provider first; absent, the order decides. */
|
|
93
|
+
isSet?: IsSet;
|
|
94
|
+
}
|
|
83
95
|
/** One thing the app needs set, as the manifest declares it. */
|
|
84
96
|
export interface AppSetting {
|
|
85
97
|
kind: SettingKind;
|
|
@@ -88,8 +100,14 @@ export interface AppSetting {
|
|
|
88
100
|
/** "OpenRouter", "DataForSEO", "MAIN_SECRET", "AI proxy routes". */
|
|
89
101
|
label: string;
|
|
90
102
|
holder: SettingHolder;
|
|
91
|
-
/** Every one of these must be set for the setting to count as set. */
|
|
103
|
+
/** Every one of these must be set for the setting to count as set (or any one group of `alternatives`). */
|
|
92
104
|
names: string[];
|
|
105
|
+
/**
|
|
106
|
+
* For the default model provider: the settings of each provider that
|
|
107
|
+
* could serve it, any one group of which, all set, makes the setting
|
|
108
|
+
* set; `names` is the first group, what to ask for.
|
|
109
|
+
*/
|
|
110
|
+
alternatives?: string[][];
|
|
93
111
|
/** Read when set, never required (a capability's optional settings). */
|
|
94
112
|
alsoReads: string[];
|
|
95
113
|
need: SettingNeed;
|
|
@@ -157,7 +175,7 @@ export declare function secretNames(manifest: Pick<SettingsManifestLike, "secret
|
|
|
157
175
|
* which is always set. `lookup` is where ids are found: the catalog alone
|
|
158
176
|
* by default, or a gateway's registry with its registered rows.
|
|
159
177
|
*/
|
|
160
|
-
export declare function appSettings(manifest: SettingsManifestLike, lookup?: CapabilityLookup): AppSetting[];
|
|
178
|
+
export declare function appSettings(manifest: SettingsManifestLike, lookup?: CapabilityLookup, options?: AppSettingsOptions): AppSetting[];
|
|
161
179
|
export interface EvaluateOptions {
|
|
162
180
|
/**
|
|
163
181
|
* A capability's own readiness rule, where names alone don't say (the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appSettings.d.ts","sourceRoot":"","sources":["../../src/internal/appSettings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAKL,KAAK,gBAAgB,EAErB,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"appSettings.d.ts","sourceRoot":"","sources":["../../src/internal/appSettings.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
* the app Worker's secret names.
|
|
24
24
|
*/
|
|
25
25
|
import { CATALOG, capabilitySettings, } from "./capabilities.js";
|
|
26
|
+
import { aiDefaultSetupHint, aiRequiredSettings, resolveAiDefault, } from "./aiDefault.js";
|
|
26
27
|
import { isInstallOwnedGatewaySetting, isSettableGatewaySetting, } from "./gatewaySettings.js";
|
|
27
28
|
import { remoteMcpAuthLabel, remoteMcpOf, remoteMcpSecretOf, } from "./remoteMcp.js";
|
|
28
29
|
/** The need an entry declares; required unless it says otherwise. */
|
|
@@ -86,7 +87,8 @@ export function secretNames(manifest) {
|
|
|
86
87
|
* registered row's are its own, so they count too.
|
|
87
88
|
*/
|
|
88
89
|
function providerNames(capability) {
|
|
89
|
-
|
|
90
|
+
// An optional key (AI Gateway's own token) is never a need.
|
|
91
|
+
return aiRequiredSettings(capability).filter((name) => !isInstallOwnedGatewaySetting(name));
|
|
90
92
|
}
|
|
91
93
|
/** A capability's Gateway settings: what it needs, and what it also reads. */
|
|
92
94
|
function capabilityNames(capability) {
|
|
@@ -173,8 +175,37 @@ function withNeed(setting, entry, defaults = {}) {
|
|
|
173
175
|
* which is always set. `lookup` is where ids are found: the catalog alone
|
|
174
176
|
* by default, or a gateway's registry with its registered rows.
|
|
175
177
|
*/
|
|
176
|
-
export function appSettings(manifest, lookup = CATALOG) {
|
|
178
|
+
export function appSettings(manifest, lookup = CATALOG, options = {}) {
|
|
177
179
|
const settings = [];
|
|
180
|
+
const chat = manifest.ai?.chat;
|
|
181
|
+
if (chat === true || (chat && typeof chat === "object")) {
|
|
182
|
+
// The default resolves on what is set: with nothing set, the first of
|
|
183
|
+
// the order (or the operator's choice) and its settings are what to
|
|
184
|
+
// ask for; with one configured, that provider's. `isSet` here only
|
|
185
|
+
// orders the candidates; evaluateAppSettings decides what is set.
|
|
186
|
+
const resolution = resolveAiDefault({
|
|
187
|
+
choice: options.aiDefault ?? null,
|
|
188
|
+
isSet: options.isSet ?? (() => false),
|
|
189
|
+
lookup,
|
|
190
|
+
});
|
|
191
|
+
const settable = (names) => names.filter((name) => !isInstallOwnedGatewaySetting(name));
|
|
192
|
+
const provider = lookup.get(resolution.provider);
|
|
193
|
+
settings.push(withNeed({
|
|
194
|
+
kind: "ai-default",
|
|
195
|
+
id: "ai-default",
|
|
196
|
+
label: `A chat model (${resolution.label})`,
|
|
197
|
+
holder: "gateway",
|
|
198
|
+
names: settable(resolution.settings),
|
|
199
|
+
alsoReads: [],
|
|
200
|
+
alternatives: resolution.candidates
|
|
201
|
+
.map((candidate) => settable(candidate.settings))
|
|
202
|
+
.filter((names) => names.length > 0),
|
|
203
|
+
}, chat === true ? undefined : chat, {
|
|
204
|
+
...(provider?.mode === "ai" ? { docs: provider.docs } : {}),
|
|
205
|
+
setup: "setup/ai.md",
|
|
206
|
+
hint: aiDefaultSetupHint(resolution),
|
|
207
|
+
}));
|
|
208
|
+
}
|
|
178
209
|
for (const entry of providerEntries(manifest)) {
|
|
179
210
|
const capability = lookup.get(entry.id);
|
|
180
211
|
if (capability?.mode !== "ai")
|
|
@@ -259,15 +290,30 @@ export function appSettings(manifest, lookup = CATALOG) {
|
|
|
259
290
|
}
|
|
260
291
|
/** Whether each name of `setting` is set: all → true, one unset → false, else unknown. */
|
|
261
292
|
function settingIsSet(setting, isSet) {
|
|
293
|
+
const groupIsSet = (names) => {
|
|
294
|
+
let unknown = false;
|
|
295
|
+
for (const name of names) {
|
|
296
|
+
const state = isSet(setting.holder, name);
|
|
297
|
+
if (state === false)
|
|
298
|
+
return false;
|
|
299
|
+
if (state === null)
|
|
300
|
+
unknown = true;
|
|
301
|
+
}
|
|
302
|
+
return unknown ? null : true;
|
|
303
|
+
};
|
|
304
|
+
if (!setting.alternatives?.length)
|
|
305
|
+
return groupIsSet(setting.names);
|
|
306
|
+
// Any one provider configured makes the default serve; unknown only
|
|
307
|
+
// when no group is set and one couldn't be read.
|
|
262
308
|
let unknown = false;
|
|
263
|
-
for (const
|
|
264
|
-
const state =
|
|
265
|
-
if (state ===
|
|
266
|
-
return
|
|
309
|
+
for (const names of setting.alternatives) {
|
|
310
|
+
const state = groupIsSet(names);
|
|
311
|
+
if (state === true)
|
|
312
|
+
return true;
|
|
267
313
|
if (state === null)
|
|
268
314
|
unknown = true;
|
|
269
315
|
}
|
|
270
|
-
return unknown ? null :
|
|
316
|
+
return unknown ? null : false;
|
|
271
317
|
}
|
|
272
318
|
/**
|
|
273
319
|
* Every setting against what is set. `isSet` answers per holder and name:
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The audit log's shared reading of an event row: who did it, what it was
|
|
3
|
+
* about, and what the type means in plain words. Admin → Activity → Audit,
|
|
4
|
+
* `everyapp workspace audit` and `everyapp_workspace_audit` all show the
|
|
5
|
+
* same columns, so the three derive them here, from the stored `actor`
|
|
6
|
+
* and `data` (the catalogue's builders decide what those hold; the
|
|
7
|
+
* gateway's `summarize` writes the one-line summary from the same data).
|
|
8
|
+
* Nothing here reads a secret, a tool's arguments or result, or a mail
|
|
9
|
+
* body: the rows never hold one.
|
|
10
|
+
*/
|
|
11
|
+
import { type EventGroup, type EventTypeInfo } from "./events.js";
|
|
12
|
+
/** Who caused an audit event, as every surface shows it. */
|
|
13
|
+
export interface AuditActor {
|
|
14
|
+
/** `user`, `agent`, `app`, `operator`, `gateway`, or what the row says. */
|
|
15
|
+
kind: string;
|
|
16
|
+
/** The user id, the credential id (an agent), the app id, the operator's id; null for the gateway. */
|
|
17
|
+
id: string | null;
|
|
18
|
+
email: string | null;
|
|
19
|
+
/** A member's name, or the AI app's name for an agent. */
|
|
20
|
+
name: string | null;
|
|
21
|
+
}
|
|
22
|
+
/** What an audit event is about, picked from its `data` by the keys the catalogue uses. */
|
|
23
|
+
export interface AuditSubject {
|
|
24
|
+
app?: {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string | null;
|
|
27
|
+
};
|
|
28
|
+
user?: {
|
|
29
|
+
id: string;
|
|
30
|
+
email: string | null;
|
|
31
|
+
name: string | null;
|
|
32
|
+
};
|
|
33
|
+
group?: {
|
|
34
|
+
id: string;
|
|
35
|
+
name: string | null;
|
|
36
|
+
};
|
|
37
|
+
provider?: {
|
|
38
|
+
id: string;
|
|
39
|
+
name: string | null;
|
|
40
|
+
};
|
|
41
|
+
mcpApp?: {
|
|
42
|
+
id: string;
|
|
43
|
+
name: string | null;
|
|
44
|
+
};
|
|
45
|
+
subscription?: {
|
|
46
|
+
id: string;
|
|
47
|
+
name: string | null;
|
|
48
|
+
};
|
|
49
|
+
/** `member.invited`: whom. */
|
|
50
|
+
invitation?: {
|
|
51
|
+
email: string;
|
|
52
|
+
role: string | null;
|
|
53
|
+
};
|
|
54
|
+
/** Setting names an event lists (never a value): unmet, changed, added, removed. */
|
|
55
|
+
settings?: string[];
|
|
56
|
+
tool?: string;
|
|
57
|
+
/** The AI app of a connection or a blocked call. */
|
|
58
|
+
client?: string;
|
|
59
|
+
/** A personal access token's name. */
|
|
60
|
+
token?: string;
|
|
61
|
+
}
|
|
62
|
+
/** The stored `actor` (a JSON string or the parsed object) as the surfaces show it. */
|
|
63
|
+
export declare function auditActorOf(actor: unknown): AuditActor;
|
|
64
|
+
/**
|
|
65
|
+
* The Who cell: a person by name or email, "agent · Claude" for an AI
|
|
66
|
+
* client, "CLI · <operator>" for the operator's command line, "app · crm"
|
|
67
|
+
* for an app's own event, "Gateway" for what the gateway did by itself.
|
|
68
|
+
*/
|
|
69
|
+
export declare function auditActorLabel(actor: AuditActor): string;
|
|
70
|
+
/** The plain-words label for a type: the catalogue's description, or "App event" for an app's own. */
|
|
71
|
+
export declare function auditTypeLabel(type: string): string;
|
|
72
|
+
/** What the event is about, from its stored `data`. */
|
|
73
|
+
export declare function auditSubjectOf(type: string, data: unknown): AuditSubject;
|
|
74
|
+
/** The Subject cell: the first thing the event is about, by name, then what else it names. */
|
|
75
|
+
export declare function auditSubjectLabel(subject: AuditSubject): string;
|
|
76
|
+
/**
|
|
77
|
+
* What the audit log leaves out unless asked for by type: `ping` (a test)
|
|
78
|
+
* and `tool.*` (the tool-calls view lists every call, blocked or not).
|
|
79
|
+
*/
|
|
80
|
+
export declare const AUDIT_DEFAULT_EXCLUDED: readonly string[];
|
|
81
|
+
/**
|
|
82
|
+
* Whether an event of `type` is in the audit log's default view, or
|
|
83
|
+
* matches the type filter given (an exact type, or a prefix like
|
|
84
|
+
* `member.*`; `*` is everything, the excluded included).
|
|
85
|
+
*/
|
|
86
|
+
export declare function auditTypeMatches(type: string, filter: string | undefined): boolean;
|
|
87
|
+
/** The SQL the filter translates to: `type = ?` or `type LIKE 'prefix.%'`; null for `*`. */
|
|
88
|
+
export declare function auditTypeCondition(filter: string): {
|
|
89
|
+
op: "eq";
|
|
90
|
+
value: string;
|
|
91
|
+
} | {
|
|
92
|
+
op: "prefix";
|
|
93
|
+
value: string;
|
|
94
|
+
} | null;
|
|
95
|
+
/** A type-filter value someone typed, cleaned, or null for none. */
|
|
96
|
+
export declare function auditTypeFilterOf(value: unknown): string | undefined;
|
|
97
|
+
export interface AuditTypeGroup {
|
|
98
|
+
group: EventGroup;
|
|
99
|
+
label: string;
|
|
100
|
+
/** `member.*` */
|
|
101
|
+
pattern: string;
|
|
102
|
+
types: EventTypeInfo[];
|
|
103
|
+
}
|
|
104
|
+
/** The groups' plain-words headings, as the Add-subscription dialog names them. */
|
|
105
|
+
export declare const AUDIT_GROUP_LABELS: Partial<Record<EventGroup, string>>;
|
|
106
|
+
/** The catalogue grouped for a type filter, in catalogue order, `ping` left out. */
|
|
107
|
+
export declare function auditTypeGroups(types?: readonly EventTypeInfo[]): AuditTypeGroup[];
|
|
108
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/internal/audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The audit log's shared reading of an event row: who did it, what it was
|
|
3
|
+
* about, and what the type means in plain words. Admin → Activity → Audit,
|
|
4
|
+
* `everyapp workspace audit` and `everyapp_workspace_audit` all show the
|
|
5
|
+
* same columns, so the three derive them here, from the stored `actor`
|
|
6
|
+
* and `data` (the catalogue's builders decide what those hold; the
|
|
7
|
+
* gateway's `summarize` writes the one-line summary from the same data).
|
|
8
|
+
* Nothing here reads a secret, a tool's arguments or result, or a mail
|
|
9
|
+
* body: the rows never hold one.
|
|
10
|
+
*/
|
|
11
|
+
import { APP_EVENT_PREFIX, EVENT_TYPES, eventPatternMatches, eventTypeInfo, isAppOwnEventType, } from "./events.js";
|
|
12
|
+
function obj(value) {
|
|
13
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
14
|
+
? value
|
|
15
|
+
: {};
|
|
16
|
+
}
|
|
17
|
+
function str(value) {
|
|
18
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
19
|
+
}
|
|
20
|
+
function strings(value) {
|
|
21
|
+
return Array.isArray(value)
|
|
22
|
+
? value.filter((item) => typeof item === "string")
|
|
23
|
+
: [];
|
|
24
|
+
}
|
|
25
|
+
/** The stored `actor` (a JSON string or the parsed object) as the surfaces show it. */
|
|
26
|
+
export function auditActorOf(actor) {
|
|
27
|
+
let parsed = actor;
|
|
28
|
+
if (typeof actor === "string") {
|
|
29
|
+
try {
|
|
30
|
+
parsed = JSON.parse(actor);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
parsed = {};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const who = obj(parsed);
|
|
37
|
+
return {
|
|
38
|
+
kind: str(who.kind) ?? "gateway",
|
|
39
|
+
id: str(who.id),
|
|
40
|
+
email: str(who.email),
|
|
41
|
+
name: str(who.name),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The Who cell: a person by name or email, "agent · Claude" for an AI
|
|
46
|
+
* client, "CLI · <operator>" for the operator's command line, "app · crm"
|
|
47
|
+
* for an app's own event, "Gateway" for what the gateway did by itself.
|
|
48
|
+
*/
|
|
49
|
+
export function auditActorLabel(actor) {
|
|
50
|
+
switch (actor.kind) {
|
|
51
|
+
case "user":
|
|
52
|
+
return actor.name ?? actor.email ?? actor.id ?? "a member";
|
|
53
|
+
case "agent":
|
|
54
|
+
return `agent · ${actor.name ?? actor.id ?? "AI app"}`;
|
|
55
|
+
case "operator":
|
|
56
|
+
return `CLI · ${actor.email ?? actor.id ?? "operator"}`;
|
|
57
|
+
case "app":
|
|
58
|
+
return `app · ${actor.id ?? "app"}`;
|
|
59
|
+
case "gateway":
|
|
60
|
+
return "Gateway";
|
|
61
|
+
default:
|
|
62
|
+
return actor.name ?? actor.email ?? actor.id ?? actor.kind;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** The plain-words label for a type: the catalogue's description, or "App event" for an app's own. */
|
|
66
|
+
export function auditTypeLabel(type) {
|
|
67
|
+
const info = eventTypeInfo(type);
|
|
68
|
+
if (info)
|
|
69
|
+
return info.description;
|
|
70
|
+
if (isAppOwnEventType(type)) {
|
|
71
|
+
const rest = type.slice(APP_EVENT_PREFIX.length);
|
|
72
|
+
return `App event: ${rest.slice(rest.indexOf(".") + 1)}`;
|
|
73
|
+
}
|
|
74
|
+
return type;
|
|
75
|
+
}
|
|
76
|
+
function named(value) {
|
|
77
|
+
const subject = obj(value);
|
|
78
|
+
const id = str(subject.id) ?? str(subject.rowId);
|
|
79
|
+
return id ? { id, name: str(subject.name) } : undefined;
|
|
80
|
+
}
|
|
81
|
+
/** What the event is about, from its stored `data`. */
|
|
82
|
+
export function auditSubjectOf(type, data) {
|
|
83
|
+
const d = obj(data);
|
|
84
|
+
const subject = {};
|
|
85
|
+
const app = named(d.app);
|
|
86
|
+
if (app) {
|
|
87
|
+
if (type.startsWith("mcp_app."))
|
|
88
|
+
subject.mcpApp = app;
|
|
89
|
+
else
|
|
90
|
+
subject.app = app;
|
|
91
|
+
}
|
|
92
|
+
else if (isAppOwnEventType(type)) {
|
|
93
|
+
const rest = type.slice(APP_EVENT_PREFIX.length);
|
|
94
|
+
subject.app = { id: rest.slice(0, rest.indexOf(".")), name: null };
|
|
95
|
+
}
|
|
96
|
+
const user = obj(d.user);
|
|
97
|
+
if (str(user.id)) {
|
|
98
|
+
subject.user = {
|
|
99
|
+
id: str(user.id),
|
|
100
|
+
email: str(user.email),
|
|
101
|
+
name: str(user.name),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const group = named(d.group);
|
|
105
|
+
if (group)
|
|
106
|
+
subject.group = group;
|
|
107
|
+
const provider = named(d.provider);
|
|
108
|
+
if (provider)
|
|
109
|
+
subject.provider = provider;
|
|
110
|
+
const subscription = named(d.subscription);
|
|
111
|
+
if (subscription)
|
|
112
|
+
subject.subscription = subscription;
|
|
113
|
+
const invitation = obj(d.invitation);
|
|
114
|
+
if (str(invitation.email)) {
|
|
115
|
+
subject.invitation = {
|
|
116
|
+
email: str(invitation.email),
|
|
117
|
+
role: str(invitation.role),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const settings = [
|
|
121
|
+
...strings(d.settings),
|
|
122
|
+
...strings(d.unmet),
|
|
123
|
+
...strings(d.changed),
|
|
124
|
+
...strings(d.names),
|
|
125
|
+
];
|
|
126
|
+
if (settings.length > 0)
|
|
127
|
+
subject.settings = [...new Set(settings)];
|
|
128
|
+
const tool = str(d.tool);
|
|
129
|
+
if (tool)
|
|
130
|
+
subject.tool = tool;
|
|
131
|
+
const client = str(obj(d.client).name) ?? str(obj(d.connection).clientName);
|
|
132
|
+
if (client)
|
|
133
|
+
subject.client = client;
|
|
134
|
+
if (type.startsWith("token.") && str(d.name))
|
|
135
|
+
subject.token = str(d.name);
|
|
136
|
+
return subject;
|
|
137
|
+
}
|
|
138
|
+
/** The Subject cell: the first thing the event is about, by name, then what else it names. */
|
|
139
|
+
export function auditSubjectLabel(subject) {
|
|
140
|
+
const parts = [];
|
|
141
|
+
const app = subject.app ?? subject.mcpApp;
|
|
142
|
+
if (app)
|
|
143
|
+
parts.push(app.name ?? app.id);
|
|
144
|
+
if (subject.user) {
|
|
145
|
+
parts.push(subject.user.name ?? subject.user.email ?? subject.user.id);
|
|
146
|
+
}
|
|
147
|
+
if (subject.invitation)
|
|
148
|
+
parts.push(subject.invitation.email);
|
|
149
|
+
if (subject.group)
|
|
150
|
+
parts.push(subject.group.name ?? subject.group.id);
|
|
151
|
+
if (subject.provider) {
|
|
152
|
+
parts.push(subject.provider.name ?? subject.provider.id);
|
|
153
|
+
}
|
|
154
|
+
if (subject.subscription) {
|
|
155
|
+
parts.push(subject.subscription.name ?? subject.subscription.id);
|
|
156
|
+
}
|
|
157
|
+
if (subject.token)
|
|
158
|
+
parts.push(subject.token);
|
|
159
|
+
if (subject.tool)
|
|
160
|
+
parts.push(subject.tool);
|
|
161
|
+
if (subject.client)
|
|
162
|
+
parts.push(subject.client);
|
|
163
|
+
if (subject.settings)
|
|
164
|
+
parts.push(subject.settings.join(", "));
|
|
165
|
+
return parts.join(" · ");
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* What the audit log leaves out unless asked for by type: `ping` (a test)
|
|
169
|
+
* and `tool.*` (the tool-calls view lists every call, blocked or not).
|
|
170
|
+
*/
|
|
171
|
+
export const AUDIT_DEFAULT_EXCLUDED = ["ping", "tool.*"];
|
|
172
|
+
/**
|
|
173
|
+
* Whether an event of `type` is in the audit log's default view, or
|
|
174
|
+
* matches the type filter given (an exact type, or a prefix like
|
|
175
|
+
* `member.*`; `*` is everything, the excluded included).
|
|
176
|
+
*/
|
|
177
|
+
export function auditTypeMatches(type, filter) {
|
|
178
|
+
if (filter === undefined) {
|
|
179
|
+
return !AUDIT_DEFAULT_EXCLUDED.some((pattern) => eventPatternMatches(pattern, type));
|
|
180
|
+
}
|
|
181
|
+
if (filter === "*")
|
|
182
|
+
return true;
|
|
183
|
+
return eventPatternMatches(filter, type);
|
|
184
|
+
}
|
|
185
|
+
/** The SQL the filter translates to: `type = ?` or `type LIKE 'prefix.%'`; null for `*`. */
|
|
186
|
+
export function auditTypeCondition(filter) {
|
|
187
|
+
if (filter === "*")
|
|
188
|
+
return null;
|
|
189
|
+
if (filter.endsWith(".*"))
|
|
190
|
+
return { op: "prefix", value: filter.slice(0, -1) };
|
|
191
|
+
return { op: "eq", value: filter };
|
|
192
|
+
}
|
|
193
|
+
/** A type-filter value someone typed, cleaned, or null for none. */
|
|
194
|
+
export function auditTypeFilterOf(value) {
|
|
195
|
+
const text = typeof value === "string" ? value.trim() : "";
|
|
196
|
+
return text.length > 0 ? text : undefined;
|
|
197
|
+
}
|
|
198
|
+
/** A group with no heading here reads as its name ("organization" → "Organization"). */
|
|
199
|
+
function groupHeading(group) {
|
|
200
|
+
const words = group.replace(/_/g, " ");
|
|
201
|
+
return words.charAt(0).toUpperCase() + words.slice(1);
|
|
202
|
+
}
|
|
203
|
+
/** The groups' plain-words headings, as the Add-subscription dialog names them. */
|
|
204
|
+
export const AUDIT_GROUP_LABELS = {
|
|
205
|
+
member: "Members",
|
|
206
|
+
app: "Apps",
|
|
207
|
+
cap: "Monthly caps",
|
|
208
|
+
tool: "Agent tool calls",
|
|
209
|
+
connection: "AI connections",
|
|
210
|
+
token: "Tokens",
|
|
211
|
+
access: "Cloudflare Access",
|
|
212
|
+
mcp_app: "MCP apps",
|
|
213
|
+
provider: "API providers",
|
|
214
|
+
ping: "Test",
|
|
215
|
+
};
|
|
216
|
+
/** The catalogue grouped for a type filter, in catalogue order, `ping` left out. */
|
|
217
|
+
export function auditTypeGroups(types = EVENT_TYPES) {
|
|
218
|
+
const groups = new Map();
|
|
219
|
+
for (const info of types) {
|
|
220
|
+
if (info.group === "ping")
|
|
221
|
+
continue;
|
|
222
|
+
const existing = groups.get(info.group);
|
|
223
|
+
if (existing)
|
|
224
|
+
existing.types.push(info);
|
|
225
|
+
else {
|
|
226
|
+
groups.set(info.group, {
|
|
227
|
+
group: info.group,
|
|
228
|
+
label: AUDIT_GROUP_LABELS[info.group] ?? groupHeading(info.group),
|
|
229
|
+
pattern: `${info.group}.*`,
|
|
230
|
+
types: [info],
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return [...groups.values()];
|
|
235
|
+
}
|