@agent-native/core 0.212.1 → 0.214.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/dist/a2a/anthropic-managed-agents.js +1 -0
- package/dist/a2a/caller-auth.js +7 -2
- package/dist/a2a/client.d.ts +1 -0
- package/dist/a2a/client.js +27 -0
- package/dist/a2a/handlers.js +15 -3
- package/dist/a2a/organization-identity.d.ts +4 -1
- package/dist/a2a/organization-identity.js +3 -1
- package/dist/a2a/server.d.ts +6 -5
- package/dist/a2a/server.js +79 -6
- package/dist/a2a-claims.d.ts +1 -0
- package/dist/a2a-claims.js +1 -0
- package/dist/agent/actions/manage-provider-key-policy.js +4 -2
- package/dist/agent/app-model-defaults.js +2 -10
- package/dist/agent/loop-settings.js +2 -10
- package/dist/appearance/actions/get-theme-family.d.ts +8 -0
- package/dist/appearance/actions/get-theme-family.js +38 -0
- package/dist/appearance/actions/set-theme-family.d.ts +7 -0
- package/dist/appearance/actions/set-theme-family.js +33 -0
- package/dist/appearance/theme-family.d.ts +13 -0
- package/dist/appearance/theme-family.js +38 -0
- package/dist/audit/actions/export-audit-events.js +1 -0
- package/dist/audit/attribution.d.ts +5 -4
- package/dist/audit/attribution.js +2 -1
- package/dist/audit/index.d.ts +1 -1
- package/dist/audit/ocsf.js +1 -0
- package/dist/audit/read-scope.js +2 -12
- package/dist/audit/record.js +1 -0
- package/dist/audit/store.js +12 -3
- package/dist/audit/types.d.ts +4 -0
- package/dist/automation/index.d.ts +1 -1
- package/dist/automations/service.js +3 -10
- package/dist/client/org/hooks.d.ts +3 -0
- package/dist/client/org/hooks.js +12 -0
- package/dist/client/theme-family.d.ts +35 -0
- package/dist/client/theme-family.js +223 -0
- package/dist/client/theme.d.ts +1 -1
- package/dist/client/theme.js +5 -2
- package/dist/client/ui/index.d.ts +1 -0
- package/dist/client/ui/index.js +1 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/connections/catalog.d.ts +1 -1
- package/dist/connections/catalog.js +7 -1
- package/dist/credentials/index.js +18 -2
- package/dist/data-widgets/index.d.ts +339 -4
- package/dist/data-widgets/index.js +150 -7
- package/dist/db/schema-snapshot.generated.js +5 -2
- package/dist/feature-flags/a2a-action-route.js +1 -0
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/file-upload/storage-settings.js +2 -9
- package/dist/framework-tools.js +2 -0
- package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
- package/dist/jobs/tools.js +2 -12
- package/dist/mcp/actions/service-token-access.js +15 -11
- package/dist/mcp/credential-issuance.js +9 -2
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +1 -1
- package/dist/org/actions.d.ts +1 -1
- package/dist/org/actions.js +3 -7
- package/dist/org/app-roles.js +10 -1
- package/dist/org/context.d.ts +1 -0
- package/dist/org/context.js +122 -24
- package/dist/org/federation.d.ts +1 -1
- package/dist/org/federation.js +2 -2
- package/dist/org/handlers.d.ts +4 -0
- package/dist/org/handlers.js +140 -44
- package/dist/org/index.d.ts +2 -1
- package/dist/org/membership.d.ts +6 -4
- package/dist/org/membership.js +7 -5
- package/dist/org/migrations.js +6 -0
- package/dist/org/plugin.d.ts +1 -0
- package/dist/org/plugin.js +9 -1
- package/dist/org/private-icon-handlers.js +4 -10
- package/dist/org/types.d.ts +2 -0
- package/dist/org/workspace-app-access.js +62 -14
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/action-discovery.js +8 -0
- package/dist/server/action-routes.d.ts +1 -0
- package/dist/server/action-routes.js +13 -1
- package/dist/server/agent-chat/context-tools.js +43 -1
- package/dist/server/agent-chat/prompt-resources.js +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-default-model-route.d.ts +1 -1
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/org-admin.js +3 -2
- package/dist/server/personal-provider-key-holders.d.ts +1 -1
- package/dist/server/personal-provider-key-holders.js +7 -2
- package/dist/server/personal-provider-key-policy.d.ts +2 -0
- package/dist/server/personal-provider-key-policy.js +21 -5
- package/dist/server/request-context.d.ts +2 -0
- package/dist/server/request-context.js +7 -0
- package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +16 -13
- package/dist/triggers/actions/manage-automation.d.ts +4 -4
- package/dist/triggers/routes.js +2 -9
- package/dist/usage/alerts-store.js +2 -9
- package/dist/usage/metrics-store.js +2 -9
- package/dist/workspace-connections/actions/list-workspace-user-groups.d.ts +1 -1
- package/dist/workspace-connections/groups.js +2 -11
- package/package.json +3 -3
- package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +16 -13
|
@@ -183,6 +183,7 @@ async function verifyContinuationToken(token, context, options) {
|
|
|
183
183
|
verified = await verifyA2AToken(token, context.event, {
|
|
184
184
|
includeClaims: true,
|
|
185
185
|
globalSecretOnly: true,
|
|
186
|
+
allowAnthropicManagedContinuation: true,
|
|
186
187
|
});
|
|
187
188
|
}
|
|
188
189
|
catch (cause) {
|
package/dist/a2a/caller-auth.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { getRequestOrgId, getRequestUserEmail, } from "../server/request-context.js";
|
|
2
|
-
import { getGlobalA2ASecret, signA2AOrganizationToken, signA2AToken, } from "./client.js";
|
|
1
|
+
import { getRequestContext, getRequestOrgId, getRequestUserEmail, } from "../server/request-context.js";
|
|
2
|
+
import { getGlobalA2ASecret, signA2AOrgMemberDelegationToken, signA2AOrganizationToken, signA2AToken, } from "./client.js";
|
|
3
3
|
const DEFAULT_A2A_CALLER_TOKEN_TTL = "5m";
|
|
4
4
|
export async function resolveA2ACallerAuth(options) {
|
|
5
5
|
const userEmail = getRequestUserEmail();
|
|
6
|
+
const isOrgMemberDelegation = getRequestContext()?.a2aIdentityAssurance === "org-member";
|
|
6
7
|
const globalSecret = getGlobalA2ASecret();
|
|
7
8
|
const metadata = {};
|
|
8
9
|
if (userEmail)
|
|
@@ -24,6 +25,7 @@ export async function resolveA2ACallerAuth(options) {
|
|
|
24
25
|
apiKeyAttempts.push(token);
|
|
25
26
|
};
|
|
26
27
|
if (userEmail &&
|
|
28
|
+
!isOrgMemberDelegation &&
|
|
27
29
|
options?.audience &&
|
|
28
30
|
globalSecret &&
|
|
29
31
|
(options?.userIdentityOnly || !orgId || orgDomain?.trim())) {
|
|
@@ -40,6 +42,9 @@ export async function resolveA2ACallerAuth(options) {
|
|
|
40
42
|
orgDomain &&
|
|
41
43
|
options?.audience &&
|
|
42
44
|
(orgSecret || globalSecret)) {
|
|
45
|
+
if (userEmail && orgSecret) {
|
|
46
|
+
addApiKeyAttempt(await signA2AOrgMemberDelegationToken(userEmail, orgDomain, orgSecret, options.audience));
|
|
47
|
+
}
|
|
43
48
|
addApiKeyAttempt(await signA2AOrganizationToken(orgDomain, orgSecret, undefined, {
|
|
44
49
|
expiresIn: options?.expiresIn ?? DEFAULT_A2A_CALLER_TOKEN_TTL,
|
|
45
50
|
audience: options?.audience,
|
package/dist/a2a/client.d.ts
CHANGED
|
@@ -64,6 +64,7 @@ export declare function signA2AOrganizationToken(orgDomain: string | undefined,
|
|
|
64
64
|
preferGlobalSecret?: boolean;
|
|
65
65
|
extraClaims?: Record<string, unknown>;
|
|
66
66
|
}): Promise<string>;
|
|
67
|
+
export declare function signA2AOrgMemberDelegationToken(email: string, orgDomain: string, orgSecret: string, audience: string | string[]): Promise<string>;
|
|
67
68
|
export declare function shouldPreferGlobalA2ASecret(orgSecret?: string): boolean;
|
|
68
69
|
export declare class A2AClient {
|
|
69
70
|
private baseUrl;
|
package/dist/a2a/client.js
CHANGED
|
@@ -8,6 +8,7 @@ import { getRequestContext } from "../server/request-context.js";
|
|
|
8
8
|
import { SYNTHETIC_TRAFFIC_BETA_E2E, SYNTHETIC_TRAFFIC_HEADER, } from "../shared/test-traffic.js";
|
|
9
9
|
import { canonicalA2AAudience } from "./audience.js";
|
|
10
10
|
import { sanitizeA2ACorrelationMetadata } from "./correlation.js";
|
|
11
|
+
import { A2A_ORG_MEMBER_DELEGATION_TYPE } from "./organization-identity.js";
|
|
11
12
|
import { RemoteAgentCredentialRejectedError } from "./remote-agent-auth.js";
|
|
12
13
|
import { workspacePrivateOrigins } from "./workspace-private-origins.js";
|
|
13
14
|
const DEFAULT_A2A_POLL_REQUEST_TIMEOUT_MS = 15_000;
|
|
@@ -172,6 +173,27 @@ export async function signA2AOrganizationToken(orgDomain, orgSecret, orgId, opti
|
|
|
172
173
|
jwt.setAudience(options.audience);
|
|
173
174
|
return jwt.sign(new TextEncoder().encode(secret));
|
|
174
175
|
}
|
|
176
|
+
export async function signA2AOrgMemberDelegationToken(email, orgDomain, orgSecret, audience) {
|
|
177
|
+
const normalizedEmail = email.trim().toLowerCase();
|
|
178
|
+
const normalizedDomain = orgDomain.trim().toLowerCase();
|
|
179
|
+
const secret = orgSecret.trim();
|
|
180
|
+
if (!normalizedEmail || !normalizedDomain || !secret || !audience) {
|
|
181
|
+
throw new Error("A member email, organization domain, organization secret, and audience are required.");
|
|
182
|
+
}
|
|
183
|
+
const appUrl = getAppConfig().app.url ?? "http://localhost:3000";
|
|
184
|
+
return new jose.SignJWT({
|
|
185
|
+
typ: A2A_ORG_MEMBER_DELEGATION_TYPE,
|
|
186
|
+
sub: normalizedEmail,
|
|
187
|
+
org_domain: normalizedDomain,
|
|
188
|
+
})
|
|
189
|
+
.setProtectedHeader({ alg: "HS256" })
|
|
190
|
+
.setIssuer(appUrl)
|
|
191
|
+
.setIssuedAt()
|
|
192
|
+
.setJti(randomUUID())
|
|
193
|
+
.setExpirationTime("5m")
|
|
194
|
+
.setAudience(audience)
|
|
195
|
+
.sign(new TextEncoder().encode(secret));
|
|
196
|
+
}
|
|
175
197
|
export function shouldPreferGlobalA2ASecret(orgSecret) {
|
|
176
198
|
return !!getGlobalA2ASecret() || !orgSecret;
|
|
177
199
|
}
|
|
@@ -1517,7 +1539,9 @@ async function buildA2AApiKeyAttempts(opts, audience) {
|
|
|
1517
1539
|
attempts.push(token);
|
|
1518
1540
|
};
|
|
1519
1541
|
const globalSecret = getGlobalA2ASecret();
|
|
1542
|
+
const isOrgMemberDelegation = getRequestContext()?.a2aIdentityAssurance === "org-member";
|
|
1520
1543
|
if (opts?.userEmail &&
|
|
1544
|
+
!isOrgMemberDelegation &&
|
|
1521
1545
|
globalSecret &&
|
|
1522
1546
|
(!opts.orgId || opts.orgDomain?.trim())) {
|
|
1523
1547
|
add(await signA2AToken(opts.userEmail, opts.orgDomain, undefined, {
|
|
@@ -1525,6 +1549,9 @@ async function buildA2AApiKeyAttempts(opts, audience) {
|
|
|
1525
1549
|
audience,
|
|
1526
1550
|
}));
|
|
1527
1551
|
}
|
|
1552
|
+
if (opts?.userEmail && opts.orgDomain && opts.orgSecret && audience) {
|
|
1553
|
+
add(await signA2AOrgMemberDelegationToken(opts.userEmail, opts.orgDomain, opts.orgSecret, audience));
|
|
1554
|
+
}
|
|
1528
1555
|
if (opts?.orgDomain && (opts.orgSecret || globalSecret)) {
|
|
1529
1556
|
add(await signA2AOrganizationToken(opts.orgDomain, opts.orgSecret, undefined, { audience }));
|
|
1530
1557
|
}
|
package/dist/a2a/handlers.js
CHANGED
|
@@ -302,9 +302,11 @@ async function processClaimedA2ATask(taskId, claimed, config, signal, event) {
|
|
|
302
302
|
const verifiedEmail = processorMeta.verifiedEmail;
|
|
303
303
|
const identityAssurance = processorMeta.identityAssurance === "organization"
|
|
304
304
|
? "organization"
|
|
305
|
-
: processorMeta.identityAssurance === "
|
|
306
|
-
? "
|
|
307
|
-
:
|
|
305
|
+
: processorMeta.identityAssurance === "org-member"
|
|
306
|
+
? "org-member"
|
|
307
|
+
: processorMeta.identityAssurance === "user"
|
|
308
|
+
? "user"
|
|
309
|
+
: undefined;
|
|
308
310
|
const orgDomainHint = processorMeta.orgDomainHint;
|
|
309
311
|
const verifiedOrgId = typeof processorMeta.verifiedOrgId === "string"
|
|
310
312
|
? processorMeta.verifiedOrgId.trim()
|
|
@@ -367,6 +369,9 @@ async function processClaimedA2ATask(taskId, claimed, config, signal, event) {
|
|
|
367
369
|
const { runWithRequestContext } = await import("../server/request-context.js");
|
|
368
370
|
await runWithRequestContext({
|
|
369
371
|
userEmail: verifiedEmail,
|
|
372
|
+
...(identityAssurance
|
|
373
|
+
? { a2aIdentityAssurance: identityAssurance }
|
|
374
|
+
: {}),
|
|
370
375
|
...(resolvedOrgId
|
|
371
376
|
? { orgId: resolvedOrgId }
|
|
372
377
|
: verifiedEmail
|
|
@@ -547,12 +552,19 @@ async function withA2ARequestContext(metadata, event, fn) {
|
|
|
547
552
|
const { runWithRequestContext } = await import("../server/request-context.js");
|
|
548
553
|
const verifiedEmail = event?.context?.__a2aVerifiedEmail ?? undefined;
|
|
549
554
|
const verifiedOrgId = event?.context?.__a2aVerifiedOrgId ?? undefined;
|
|
555
|
+
const rawIdentityAssurance = event?.context?.__a2aIdentityAssurance;
|
|
556
|
+
const identityAssurance = rawIdentityAssurance === "user" ||
|
|
557
|
+
rawIdentityAssurance === "organization" ||
|
|
558
|
+
rawIdentityAssurance === "org-member"
|
|
559
|
+
? rawIdentityAssurance
|
|
560
|
+
: undefined;
|
|
550
561
|
const requestOrigin = requestOriginForContext(metadata, event);
|
|
551
562
|
if (event?.context && verifiedEmail && !verifiedOrgId) {
|
|
552
563
|
markExplicitPersonalOrgScope(event);
|
|
553
564
|
}
|
|
554
565
|
return runWithRequestContext({
|
|
555
566
|
userEmail: verifiedEmail,
|
|
567
|
+
...(identityAssurance ? { a2aIdentityAssurance: identityAssurance } : {}),
|
|
556
568
|
...(verifiedOrgId
|
|
557
569
|
? { orgId: verifiedOrgId }
|
|
558
570
|
: verifiedEmail
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { JWTPayload } from "jose";
|
|
2
|
+
export declare const A2A_ORG_MEMBER_DELEGATION_TYPE = "agent-native-org-member-delegation";
|
|
2
3
|
export interface VerifiedA2AOrganizationIdentity {
|
|
3
4
|
orgId: string;
|
|
4
5
|
orgDomain: string | null;
|
|
@@ -6,10 +7,12 @@ export interface VerifiedA2AOrganizationIdentity {
|
|
|
6
7
|
export interface A2AOrganizationCredential extends VerifiedA2AOrganizationIdentity {
|
|
7
8
|
orgDomain: string;
|
|
8
9
|
secret: string;
|
|
10
|
+
a2aMemberDelegationEnabled?: boolean;
|
|
9
11
|
}
|
|
10
12
|
/**
|
|
11
13
|
* An organization secret authenticates an organization principal. Its JWT
|
|
12
|
-
* subject is caller-controlled data
|
|
14
|
+
* subject is caller-controlled data unless it is an opted-in, audience-bound
|
|
15
|
+
* member delegation verified against the receiver's current roster.
|
|
13
16
|
*/
|
|
14
17
|
export declare function organizationPrincipalClaims(payload: JWTPayload, organization: A2AOrganizationCredential): JWTPayload | null;
|
|
15
18
|
/**
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
export const A2A_ORG_MEMBER_DELEGATION_TYPE = "agent-native-org-member-delegation";
|
|
1
2
|
/**
|
|
2
3
|
* An organization secret authenticates an organization principal. Its JWT
|
|
3
|
-
* subject is caller-controlled data
|
|
4
|
+
* subject is caller-controlled data unless it is an opted-in, audience-bound
|
|
5
|
+
* member delegation verified against the receiver's current roster.
|
|
4
6
|
*/
|
|
5
7
|
export function organizationPrincipalClaims(payload, organization) {
|
|
6
8
|
const orgDomain = typeof payload.org_domain === "string"
|
package/dist/a2a/server.d.ts
CHANGED
|
@@ -2,16 +2,15 @@ import * as jose from "jose";
|
|
|
2
2
|
import "../authorization/check-action.js";
|
|
3
3
|
import type { A2AConfig, AgentSkill } from "./types.js";
|
|
4
4
|
/**
|
|
5
|
-
* Result of verifying an inbound A2A JWT. `email` is present
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* `orgId` are bound to local organization metadata when present.
|
|
5
|
+
* Result of verifying an inbound A2A JWT. `email` is present for deployment
|
|
6
|
+
* user assertions or an explicitly opted-in org-member delegation. `orgDomain`
|
|
7
|
+
* and `orgId` are bound to local organization metadata when present.
|
|
9
8
|
*/
|
|
10
9
|
export interface A2ATokenPayload {
|
|
11
10
|
email: string | null;
|
|
12
11
|
orgDomain: string | null;
|
|
13
12
|
orgId?: string;
|
|
14
|
-
identityAssurance?: "user" | "organization";
|
|
13
|
+
identityAssurance?: "user" | "organization" | "org-member";
|
|
15
14
|
claims?: jose.JWTPayload;
|
|
16
15
|
}
|
|
17
16
|
export declare class A2AIdentityVerificationUnavailableError extends Error {
|
|
@@ -47,6 +46,8 @@ export declare function verifyA2AToken(token: string, event?: any, audienceOptio
|
|
|
47
46
|
globalSecretOnly?: boolean;
|
|
48
47
|
/** Only use this explicitly configured credential; never fall back. */
|
|
49
48
|
verificationSecret?: string;
|
|
49
|
+
/** Dedicated verifier for the typed Anthropic continuation credential. */
|
|
50
|
+
allowAnthropicManagedContinuation?: boolean;
|
|
50
51
|
requireAudience?: boolean;
|
|
51
52
|
}): Promise<A2ATokenPayload>;
|
|
52
53
|
export type A2ATokenFailureCause = "malformed" | "secret-missing" | "audience-unresolvable" | "audience" | "issuer" | "expired" | "signature" | "invalid-claims" | "mcp-credential" | "missing-subject" | "org-binding" | "org-lookup-failed" | "undetermined";
|
package/dist/a2a/server.js
CHANGED
|
@@ -19,7 +19,7 @@ import { addAgentProfileExamples } from "./app-profile.js";
|
|
|
19
19
|
import { canonicalA2AAudience } from "./audience.js";
|
|
20
20
|
import { hasConfiguredA2ASecret, isA2AProductionRuntime, } from "./auth-policy.js";
|
|
21
21
|
import { handleJsonRpcH3, processA2ATaskFromQueue } from "./handlers.js";
|
|
22
|
-
import { organizationPrincipalClaims, verifyA2AOrganizationIdentity, } from "./organization-identity.js";
|
|
22
|
+
import { A2A_ORG_MEMBER_DELEGATION_TYPE, organizationPrincipalClaims, verifyA2AOrganizationIdentity, } from "./organization-identity.js";
|
|
23
23
|
import { claimA2AApproval, a2aTaskLeaseThreadId, getA2AApprovalForOwner, settleA2AApproval, } from "./task-store.js";
|
|
24
24
|
let _warnedUnauthA2A = false;
|
|
25
25
|
function warnA2AUnauthOnce() {
|
|
@@ -59,7 +59,7 @@ export function isA2AIdentityVerificationUnavailableError(error) {
|
|
|
59
59
|
(error instanceof Error &&
|
|
60
60
|
error.name === "A2AIdentityVerificationUnavailableError"));
|
|
61
61
|
}
|
|
62
|
-
function identityPayload(payload, audienceOptions, verifiedOrganization) {
|
|
62
|
+
function identityPayload(payload, audienceOptions, verifiedOrganization, identityAssurance) {
|
|
63
63
|
const email = typeof payload.sub === "string" && payload.sub.trim()
|
|
64
64
|
? payload.sub.trim()
|
|
65
65
|
: null;
|
|
@@ -79,9 +79,34 @@ function identityPayload(payload, audienceOptions, verifiedOrganization) {
|
|
|
79
79
|
...(!email && verifiedOrganization
|
|
80
80
|
? { identityAssurance: "organization" }
|
|
81
81
|
: {}),
|
|
82
|
+
...(identityAssurance ? { identityAssurance } : {}),
|
|
82
83
|
...(audienceOptions?.includeClaims ? { claims } : {}),
|
|
83
84
|
};
|
|
84
85
|
}
|
|
86
|
+
function validOrgMemberDelegationClaims(payload) {
|
|
87
|
+
const email = typeof payload.sub === "string" ? payload.sub.trim() : "";
|
|
88
|
+
const jti = typeof payload.jti === "string" ? payload.jti.trim() : "";
|
|
89
|
+
const issuedAt = payload.iat;
|
|
90
|
+
const expiresAt = payload.exp;
|
|
91
|
+
const now = Math.floor(Date.now() / 1_000);
|
|
92
|
+
const audiences = Array.isArray(payload.aud) ? payload.aud : [payload.aud];
|
|
93
|
+
return (payload.typ === A2A_ORG_MEMBER_DELEGATION_TYPE &&
|
|
94
|
+
email.length <= 320 &&
|
|
95
|
+
email.includes("@") &&
|
|
96
|
+
!/[\u0000-\u001f\u007f]/.test(email) &&
|
|
97
|
+
jti.length > 0 &&
|
|
98
|
+
jti.length <= 128 &&
|
|
99
|
+
!/[\u0000-\u001f\u007f]/.test(jti) &&
|
|
100
|
+
typeof issuedAt === "number" &&
|
|
101
|
+
Number.isSafeInteger(issuedAt) &&
|
|
102
|
+
typeof expiresAt === "number" &&
|
|
103
|
+
Number.isSafeInteger(expiresAt) &&
|
|
104
|
+
issuedAt <= now + 60 &&
|
|
105
|
+
expiresAt > now &&
|
|
106
|
+
expiresAt > issuedAt &&
|
|
107
|
+
expiresAt - issuedAt <= 15 * 60 &&
|
|
108
|
+
audiences.some((audience) => typeof audience === "string" && audience.trim()));
|
|
109
|
+
}
|
|
85
110
|
async function verifyJwtWithSecret(token, secret, options) {
|
|
86
111
|
try {
|
|
87
112
|
const { payload } = await jose.jwtVerify(token, new TextEncoder().encode(secret), options);
|
|
@@ -327,6 +352,17 @@ async function verifyA2ATokenInternal(token, event, audienceOptions) {
|
|
|
327
352
|
if (globalSecret) {
|
|
328
353
|
const payload = await verifyJwtWithSecret(token, globalSecret, verifyOptions);
|
|
329
354
|
if (payload) {
|
|
355
|
+
// Typed credentials have their own verifier. Only the managed-agent
|
|
356
|
+
// confirmation verifier may accept its continuation token here.
|
|
357
|
+
if (typeof payload.typ !== "undefined") {
|
|
358
|
+
const managedContinuation = payload.typ === "anthropic-managed-continuation" &&
|
|
359
|
+
audienceOptions?.globalSecretOnly === true &&
|
|
360
|
+
audienceOptions.allowAnthropicManagedContinuation === true &&
|
|
361
|
+
audienceOptions.includeClaims === true;
|
|
362
|
+
if (!managedContinuation) {
|
|
363
|
+
return { payload: { email: null, orgDomain: null } };
|
|
364
|
+
}
|
|
365
|
+
}
|
|
330
366
|
if (typeof payload.org_domain === "string" && payload.org_domain.trim()) {
|
|
331
367
|
let organization;
|
|
332
368
|
try {
|
|
@@ -388,12 +424,49 @@ async function verifyA2ATokenInternal(token, event, audienceOptions) {
|
|
|
388
424
|
}
|
|
389
425
|
if (!organization)
|
|
390
426
|
return { payload: { email: null, orgDomain: null } };
|
|
391
|
-
const
|
|
427
|
+
const orgVerifyOptions = unverifiedPayload?.typ === A2A_ORG_MEMBER_DELEGATION_TYPE
|
|
428
|
+
? { ...verifyOptions, algorithms: ["HS256"] }
|
|
429
|
+
: verifyOptions;
|
|
430
|
+
const payload = await verifyJwtWithSecret(token, organization.secret, orgVerifyOptions);
|
|
392
431
|
if (!payload)
|
|
393
432
|
return { payload: { email: null, orgDomain: null } };
|
|
394
433
|
const claims = organizationPrincipalClaims(payload, organization);
|
|
395
434
|
if (!claims)
|
|
396
435
|
return { payload: { email: null, orgDomain: null } };
|
|
436
|
+
if (payload.typ === A2A_ORG_MEMBER_DELEGATION_TYPE) {
|
|
437
|
+
if (!validOrgMemberDelegationClaims(payload)) {
|
|
438
|
+
return { payload: { email: null, orgDomain: null } };
|
|
439
|
+
}
|
|
440
|
+
if (organization.secret.trim() === globalSecret) {
|
|
441
|
+
return { payload: { email: null, orgDomain: null } };
|
|
442
|
+
}
|
|
443
|
+
let isCurrentMember = false;
|
|
444
|
+
if (organization.a2aMemberDelegationEnabled) {
|
|
445
|
+
try {
|
|
446
|
+
const { isOrgMemberForA2A } = await import("../org/membership.js");
|
|
447
|
+
isCurrentMember = await isOrgMemberForA2A(organization.orgId, String(payload.sub).trim(), event);
|
|
448
|
+
}
|
|
449
|
+
catch (cause) {
|
|
450
|
+
throw new A2AIdentityVerificationUnavailableError(cause);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
if (isCurrentMember) {
|
|
454
|
+
return {
|
|
455
|
+
payload: identityPayload(payload, audienceOptions, organization, "org-member"),
|
|
456
|
+
verifiedOrgId: organization.orgId,
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
return {
|
|
460
|
+
payload: {
|
|
461
|
+
email: null,
|
|
462
|
+
orgDomain: organization.orgDomain,
|
|
463
|
+
orgId: organization.orgId,
|
|
464
|
+
identityAssurance: "organization",
|
|
465
|
+
...(audienceOptions?.includeClaims ? { claims } : {}),
|
|
466
|
+
},
|
|
467
|
+
verifiedOrgId: organization.orgId,
|
|
468
|
+
};
|
|
469
|
+
}
|
|
397
470
|
warnUserAssertionDemotedOnce(organization.orgId, payload, "user token verified only with org secret");
|
|
398
471
|
return {
|
|
399
472
|
payload: {
|
|
@@ -742,9 +815,9 @@ export function mountA2A(nitroApp, config, routePrefix = "/_agent-native") {
|
|
|
742
815
|
}
|
|
743
816
|
verifiedCallerEmail = tokenPayload.email;
|
|
744
817
|
verifiedOrgDomain = tokenPayload.orgDomain;
|
|
745
|
-
verifiedIdentityAssurance =
|
|
746
|
-
|
|
747
|
-
|
|
818
|
+
verifiedIdentityAssurance =
|
|
819
|
+
tokenPayload.identityAssurance ??
|
|
820
|
+
(tokenPayload.email ? "user" : undefined);
|
|
748
821
|
bearerTokenVerified = verifiedIdentityAssurance !== undefined;
|
|
749
822
|
verifiedAudienceBound =
|
|
750
823
|
bearerTokenVerified && tokenHasAudienceClaim(bearerToken);
|
package/dist/a2a-claims.d.ts
CHANGED
package/dist/a2a-claims.js
CHANGED
|
@@ -92,7 +92,7 @@ export default defineAction({
|
|
|
92
92
|
return {
|
|
93
93
|
...policy,
|
|
94
94
|
canManage,
|
|
95
|
-
affectedMembers: await listPersonalProviderKeyHolders(orgId),
|
|
95
|
+
affectedMembers: await listPersonalProviderKeyHolders(orgId, email),
|
|
96
96
|
changed,
|
|
97
97
|
};
|
|
98
98
|
}
|
|
@@ -101,7 +101,9 @@ export default defineAction({
|
|
|
101
101
|
...policy,
|
|
102
102
|
canManage,
|
|
103
103
|
...(canManage
|
|
104
|
-
? {
|
|
104
|
+
? {
|
|
105
|
+
affectedMembers: await listPersonalProviderKeyHolders(orgId, email),
|
|
106
|
+
}
|
|
105
107
|
: {}),
|
|
106
108
|
};
|
|
107
109
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readOrgMemberRole } from "../server/personal-provider-key-policy.js";
|
|
2
2
|
import { getRequestContext, getRequestOrgId, getRequestUserEmail, } from "../server/request-context.js";
|
|
3
3
|
import { deleteOrgSetting, deleteUserSetting, getOrgSetting, getUserSetting, putOrgSetting, putUserSetting, } from "../settings/index.js";
|
|
4
4
|
export const AGENT_APP_MODEL_DEFAULT_KEY_PREFIX = "agent-app-model-default";
|
|
@@ -116,15 +116,7 @@ export async function canUpdateAgentAppModelDefaultSettings(userEmail, orgId, or
|
|
|
116
116
|
if (!orgId)
|
|
117
117
|
return orgScope === "personal";
|
|
118
118
|
try {
|
|
119
|
-
const
|
|
120
|
-
const { rows } = await exec.execute({
|
|
121
|
-
sql: `SELECT role FROM org_members
|
|
122
|
-
WHERE org_id = ? AND LOWER(email) = ?
|
|
123
|
-
AND federation_removal_pending_at IS NULL
|
|
124
|
-
LIMIT 1`,
|
|
125
|
-
args: [orgId, userEmail.toLowerCase()],
|
|
126
|
-
});
|
|
127
|
-
const role = String(rows[0]?.role ?? "");
|
|
119
|
+
const role = await readOrgMemberRole(orgId, userEmail);
|
|
128
120
|
return role === "owner" || role === "admin";
|
|
129
121
|
}
|
|
130
122
|
catch {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readOrgMemberRole } from "../server/personal-provider-key-policy.js";
|
|
2
2
|
import { getOrgSetting, putOrgSetting, deleteOrgSetting, getUserSetting, putUserSetting, deleteUserSetting, } from "../settings/index.js";
|
|
3
3
|
export const AGENT_LOOP_SETTINGS_KEY = "agent-loop";
|
|
4
4
|
export const DEFAULT_AGENT_MAX_ITERATIONS = 400;
|
|
@@ -169,15 +169,7 @@ export async function canUpdateAgentLoopSettings(userEmail, orgId) {
|
|
|
169
169
|
if (!orgId)
|
|
170
170
|
return true;
|
|
171
171
|
try {
|
|
172
|
-
const
|
|
173
|
-
const { rows } = await exec.execute({
|
|
174
|
-
sql: `SELECT role FROM org_members
|
|
175
|
-
WHERE org_id = ? AND LOWER(email) = ?
|
|
176
|
-
AND federation_removal_pending_at IS NULL
|
|
177
|
-
LIMIT 1`,
|
|
178
|
-
args: [orgId, userEmail.toLowerCase()],
|
|
179
|
-
});
|
|
180
|
-
const role = String(rows[0]?.role ?? "");
|
|
172
|
+
const role = await readOrgMemberRole(orgId, userEmail);
|
|
181
173
|
return role === "owner" || role === "admin";
|
|
182
174
|
}
|
|
183
175
|
catch {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ThemeFamily } from "../theme-family.js";
|
|
2
|
+
export interface ThemeFamilyPreference {
|
|
3
|
+
family: ThemeFamily;
|
|
4
|
+
source: "default" | "user-setting";
|
|
5
|
+
appId: string | null;
|
|
6
|
+
}
|
|
7
|
+
declare const _default: import("../../action.js").ActionDefinition<Record<string, never>, ThemeFamilyPreference>;
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { defineAction, fail } from "../../action.js";
|
|
3
|
+
import { getUserSetting } from "../../settings/user-settings.js";
|
|
4
|
+
import { DEFAULT_THEME_FAMILY, THEME_FAMILIES, themeFamilySettingKey, } from "../theme-family.js";
|
|
5
|
+
export default defineAction({
|
|
6
|
+
description: "Read the current app's saved theme family, which is independent of light or dark color mode.",
|
|
7
|
+
schema: z.object({}),
|
|
8
|
+
http: { method: "GET" },
|
|
9
|
+
readOnly: true,
|
|
10
|
+
agentTool: false,
|
|
11
|
+
run: async (_args, ctx) => {
|
|
12
|
+
const email = ctx?.userEmail;
|
|
13
|
+
if (!email)
|
|
14
|
+
fail("Not authenticated.", { statusCode: 401 });
|
|
15
|
+
const stored = await getUserSetting(email, themeFamilySettingKey(ctx?.appId));
|
|
16
|
+
if (stored === null) {
|
|
17
|
+
return {
|
|
18
|
+
family: DEFAULT_THEME_FAMILY,
|
|
19
|
+
source: "default",
|
|
20
|
+
appId: ctx?.appId ?? null,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
const parsed = z
|
|
24
|
+
.object({ family: z.enum(THEME_FAMILIES) })
|
|
25
|
+
.safeParse(stored);
|
|
26
|
+
if (!parsed.success) {
|
|
27
|
+
fail("The saved theme family setting is invalid and could not be read.", {
|
|
28
|
+
errorCode: "theme_family_setting_invalid",
|
|
29
|
+
statusCode: 500,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
family: parsed.data.family,
|
|
34
|
+
source: "user-setting",
|
|
35
|
+
appId: ctx?.appId ?? null,
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { defineAction, fail } from "../../action.js";
|
|
3
|
+
import { writeAppState } from "../../application-state/script-helpers.js";
|
|
4
|
+
import { putUserSetting } from "../../settings/user-settings.js";
|
|
5
|
+
import { THEME_FAMILIES, themeFamilyAppStateKey, themeFamilySettingKey, } from "../theme-family.js";
|
|
6
|
+
export default defineAction({
|
|
7
|
+
description: "Set the current app's theme family to agent-native or original. This is separate from light or dark color mode.",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
family: z
|
|
10
|
+
.enum(THEME_FAMILIES)
|
|
11
|
+
.describe("Theme family: agent-native or original."),
|
|
12
|
+
}),
|
|
13
|
+
http: { method: "POST" },
|
|
14
|
+
mcpAnnotations: {
|
|
15
|
+
readOnlyHint: false,
|
|
16
|
+
destructiveHint: false,
|
|
17
|
+
openWorldHint: false,
|
|
18
|
+
},
|
|
19
|
+
run: async ({ family }, ctx) => {
|
|
20
|
+
const email = ctx?.userEmail;
|
|
21
|
+
if (!email)
|
|
22
|
+
fail("Not authenticated.", { statusCode: 401 });
|
|
23
|
+
const settingKey = themeFamilySettingKey(ctx?.appId);
|
|
24
|
+
await putUserSetting(email, settingKey, { family });
|
|
25
|
+
try {
|
|
26
|
+
await writeAppState(themeFamilyAppStateKey(ctx?.appId), { family });
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
fail("The theme family was saved, but the open app could not be synchronized.", { errorCode: "theme_family_sync_failed", statusCode: 503 });
|
|
30
|
+
}
|
|
31
|
+
return { family, appId: ctx?.appId ?? null };
|
|
32
|
+
},
|
|
33
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const THEME_FAMILIES: readonly ["agent-native", "original"];
|
|
2
|
+
export type ThemeFamily = (typeof THEME_FAMILIES)[number];
|
|
3
|
+
export declare const DEFAULT_THEME_FAMILY: ThemeFamily;
|
|
4
|
+
export declare const THEME_FAMILY_STORAGE_KEY = "theme-family";
|
|
5
|
+
export declare const THEME_FAMILY_ATTRIBUTE = "data-theme-family";
|
|
6
|
+
export declare const THEME_FAMILY_STATUS_ATTRIBUTE = "data-theme-family-status";
|
|
7
|
+
export declare const THEME_FAMILY_APP_STATE_KEY = "theme-family";
|
|
8
|
+
export declare const THEME_FAMILY_SETTING_PREFIX = "theme-family";
|
|
9
|
+
export declare function isThemeFamily(value: unknown): value is ThemeFamily;
|
|
10
|
+
export declare function themeFamilySettingKey(appId?: string): string;
|
|
11
|
+
export declare function themeFamilyStorageKey(appId?: string): string;
|
|
12
|
+
export declare function themeFamilyAppStateKey(appId?: string): string;
|
|
13
|
+
export declare function getThemeFamilyInitScript(appId?: string | null): string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export const THEME_FAMILIES = ["agent-native", "original"];
|
|
2
|
+
export const DEFAULT_THEME_FAMILY = "original";
|
|
3
|
+
export const THEME_FAMILY_STORAGE_KEY = "theme-family";
|
|
4
|
+
export const THEME_FAMILY_ATTRIBUTE = "data-theme-family";
|
|
5
|
+
export const THEME_FAMILY_STATUS_ATTRIBUTE = "data-theme-family-status";
|
|
6
|
+
export const THEME_FAMILY_APP_STATE_KEY = "theme-family";
|
|
7
|
+
export const THEME_FAMILY_SETTING_PREFIX = "theme-family";
|
|
8
|
+
export function isThemeFamily(value) {
|
|
9
|
+
return value === "agent-native" || value === "original";
|
|
10
|
+
}
|
|
11
|
+
export function themeFamilySettingKey(appId) {
|
|
12
|
+
// Older or standalone action contexts can genuinely omit appId. Keep their
|
|
13
|
+
// setting isolated under one stable fallback rather than borrowing another app's choice.
|
|
14
|
+
if (appId === undefined)
|
|
15
|
+
return `${THEME_FAMILY_SETTING_PREFIX}:__no_app_id__`;
|
|
16
|
+
const normalizedAppId = appId.trim().toLowerCase();
|
|
17
|
+
if (!normalizedAppId) {
|
|
18
|
+
throw new TypeError("Theme family settings require a non-empty appId.");
|
|
19
|
+
}
|
|
20
|
+
return `${THEME_FAMILY_SETTING_PREFIX}:${encodeURIComponent(normalizedAppId)}`;
|
|
21
|
+
}
|
|
22
|
+
export function themeFamilyStorageKey(appId) {
|
|
23
|
+
return themeFamilySettingKey(appId);
|
|
24
|
+
}
|
|
25
|
+
export function themeFamilyAppStateKey(appId) {
|
|
26
|
+
if (appId === undefined)
|
|
27
|
+
return `${THEME_FAMILY_APP_STATE_KEY}:__no_app_id__`;
|
|
28
|
+
const normalizedAppId = appId.trim().toLowerCase();
|
|
29
|
+
if (!normalizedAppId) {
|
|
30
|
+
throw new TypeError("Theme family application state requires a non-empty appId.");
|
|
31
|
+
}
|
|
32
|
+
const encodedAppId = Array.from(normalizedAppId, (character) => character.codePointAt(0).toString(16)).join("_");
|
|
33
|
+
return `${THEME_FAMILY_APP_STATE_KEY}:${encodedAppId}`;
|
|
34
|
+
}
|
|
35
|
+
export function getThemeFamilyInitScript(appId) {
|
|
36
|
+
const storageKey = themeFamilyStorageKey(appId ?? undefined);
|
|
37
|
+
return `(function(){var root=document.documentElement;var fallback=${JSON.stringify(DEFAULT_THEME_FAMILY)};try{var value=window.localStorage.getItem(${JSON.stringify(storageKey)});if(value===null){root.setAttribute(${JSON.stringify(THEME_FAMILY_ATTRIBUTE)},fallback);root.setAttribute(${JSON.stringify(THEME_FAMILY_STATUS_ATTRIBUTE)},'awaiting-app-setting');return}if(value==='agent-native'||value==='original'){root.setAttribute(${JSON.stringify(THEME_FAMILY_ATTRIBUTE)},value);root.removeAttribute(${JSON.stringify(THEME_FAMILY_STATUS_ATTRIBUTE)});return}root.setAttribute(${JSON.stringify(THEME_FAMILY_ATTRIBUTE)},fallback);root.setAttribute(${JSON.stringify(THEME_FAMILY_STATUS_ATTRIBUTE)},'invalid')}catch(e){root.setAttribute(${JSON.stringify(THEME_FAMILY_ATTRIBUTE)},fallback);root.setAttribute(${JSON.stringify(THEME_FAMILY_STATUS_ATTRIBUTE)},'unreadable')}})();`;
|
|
38
|
+
}
|
|
@@ -26,6 +26,7 @@ const CSV_COLUMNS = [
|
|
|
26
26
|
["reportedClientVersion", "reported_client_version"],
|
|
27
27
|
["oauthClientId", "oauth_client_id"],
|
|
28
28
|
["approval", "approval"],
|
|
29
|
+
["identityAssurance", "identity_assurance"],
|
|
29
30
|
];
|
|
30
31
|
function csvField(value) {
|
|
31
32
|
if (value === null || value === undefined)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AuditApproval } from "./types.js";
|
|
1
|
+
import type { AuditApproval, AuditIdentityAssurance } from "./types.js";
|
|
2
2
|
declare const auditAttributionBrand: unique symbol;
|
|
3
3
|
interface AuditAttributionFields {
|
|
4
4
|
caller: string;
|
|
@@ -16,11 +16,12 @@ interface AuditAttributionFields {
|
|
|
16
16
|
};
|
|
17
17
|
mcpClientAccepted?: true;
|
|
18
18
|
approval?: AuditApproval;
|
|
19
|
+
identityAssurance?: AuditIdentityAssurance;
|
|
19
20
|
}
|
|
20
21
|
/**
|
|
21
22
|
* Where an audited call came from and what vouched for it: its source, the
|
|
22
|
-
* MCP client it reported, the OAuth client of its credential,
|
|
23
|
-
* signal, and its run and network ids. `recordActionAudit` requires one and
|
|
23
|
+
* MCP client it reported, the OAuth client of its credential, verified A2A
|
|
24
|
+
* identity assurance, the approval signal, and its run and network ids. `recordActionAudit` requires one and
|
|
24
25
|
* only {@link auditAttribution} makes one, so a recorder cannot build its own
|
|
25
26
|
* context and store nulls for a field it forgot.
|
|
26
27
|
*/
|
|
@@ -38,7 +39,7 @@ export type AuditOverride = Partial<Pick<AuditAttributionFields, "threadId" | "t
|
|
|
38
39
|
* The run context attribution reads from; an `ActionRunContext` is one.
|
|
39
40
|
* Approval is not read from it: a context can be handed to another action.
|
|
40
41
|
*/
|
|
41
|
-
export type AuditAttributionSource = Partial<Omit<AuditAttributionFields, "approval" | "approvedToolCallKey" | "mcpClientAccepted">>;
|
|
42
|
+
export type AuditAttributionSource = Partial<Omit<AuditAttributionFields, "approval" | "approvedToolCallKey" | "mcpClientAccepted" | "identityAssurance">>;
|
|
42
43
|
/** A recorder was given no attribution, or one `auditAttribution` did not make. */
|
|
43
44
|
export declare class AuditAttributionError extends Error {
|
|
44
45
|
constructor(recorder: string);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { currentInvocationEvidence } from "../action-frame.js";
|
|
2
|
-
import { getVerifiedMcpCredentialFromEvent } from "../server/request-context.js";
|
|
2
|
+
import { getRequestContext, getVerifiedMcpCredentialFromEvent, } from "../server/request-context.js";
|
|
3
3
|
// Registered, so an attribution made by another loaded copy of this module
|
|
4
4
|
// still passes the check.
|
|
5
5
|
const auditAttributionBrand = Symbol.for("@agent-native/core/audit-attribution");
|
|
@@ -40,6 +40,7 @@ export function auditAttribution(ctx) {
|
|
|
40
40
|
mcpClient: ctx?.mcpClient,
|
|
41
41
|
mcpClientAccepted: evidence?.mcpClientAccepted,
|
|
42
42
|
approval: override?.approval,
|
|
43
|
+
identityAssurance: getRequestContext()?.a2aIdentityAssurance,
|
|
43
44
|
};
|
|
44
45
|
return { ...fields, [auditAttributionBrand]: true };
|
|
45
46
|
}
|
package/dist/audit/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { ActionAuditConfig, AuditActorKind, AuditApproval, AuditCallMeta, AuditEvent, AuditQueryFilters, AuditStatus, AuditTarget, AuditVisibility, } from "./types.js";
|
|
1
|
+
export type { ActionAuditConfig, AuditActorKind, AuditApproval, AuditCallMeta, AuditEvent, AuditIdentityAssurance, AuditQueryFilters, AuditStatus, AuditTarget, AuditVisibility, } from "./types.js";
|
|
2
2
|
export { AGENT_AUDIT_CALLERS, deriveActorKind, isAuditDisabled, normalizeAuditConfig, resolveAuditAttach, shouldRecordAudit, } from "./config.js";
|
|
3
3
|
export { redactArgsToJson } from "./redact.js";
|
|
4
4
|
export { ensureAuditTables, insertAuditEvent, queryAuditEvents, queryAuditEventPage, queryAuditApps, getAuditEventById, deleteOldAuditEvents, type AuditEventPage, type AuditReadScope, type AuditTrail, } from "./store.js";
|