@apart-tech/intelligence-core 1.11.4 → 1.11.5

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.
Files changed (85) hide show
  1. package/dist/auth/ability.d.ts +148 -0
  2. package/dist/auth/ability.d.ts.map +1 -0
  3. package/dist/auth/ability.js +285 -0
  4. package/dist/auth/ability.js.map +1 -0
  5. package/dist/auth/ability.test.d.ts +2 -0
  6. package/dist/auth/ability.test.d.ts.map +1 -0
  7. package/dist/auth/ability.test.js +680 -0
  8. package/dist/auth/ability.test.js.map +1 -0
  9. package/dist/auth/delegation-jwt.d.ts +167 -0
  10. package/dist/auth/delegation-jwt.d.ts.map +1 -0
  11. package/dist/auth/delegation-jwt.js +237 -0
  12. package/dist/auth/delegation-jwt.js.map +1 -0
  13. package/dist/auth/delegation-jwt.test.d.ts +2 -0
  14. package/dist/auth/delegation-jwt.test.d.ts.map +1 -0
  15. package/dist/auth/delegation-jwt.test.js +283 -0
  16. package/dist/auth/delegation-jwt.test.js.map +1 -0
  17. package/dist/auth/principal.d.ts +94 -0
  18. package/dist/auth/principal.d.ts.map +1 -0
  19. package/dist/auth/principal.js +33 -0
  20. package/dist/auth/principal.js.map +1 -0
  21. package/dist/config/config.test.d.ts +2 -0
  22. package/dist/config/config.test.d.ts.map +1 -0
  23. package/dist/config/config.test.js +57 -0
  24. package/dist/config/config.test.js.map +1 -0
  25. package/dist/config/index.d.ts.map +1 -1
  26. package/dist/config/index.js +17 -0
  27. package/dist/config/index.js.map +1 -1
  28. package/dist/index.d.ts +13 -1
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +6 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/lib/__tests__/jwt.test.d.ts +2 -0
  33. package/dist/lib/__tests__/jwt.test.d.ts.map +1 -0
  34. package/dist/lib/__tests__/jwt.test.js +97 -0
  35. package/dist/lib/__tests__/jwt.test.js.map +1 -0
  36. package/dist/lib/jwt.d.ts +20 -0
  37. package/dist/lib/jwt.d.ts.map +1 -1
  38. package/dist/lib/jwt.js +56 -3
  39. package/dist/lib/jwt.js.map +1 -1
  40. package/dist/services/__tests__/delegation-cleanup-service.test.d.ts +2 -0
  41. package/dist/services/__tests__/delegation-cleanup-service.test.d.ts.map +1 -0
  42. package/dist/services/__tests__/delegation-cleanup-service.test.js +211 -0
  43. package/dist/services/__tests__/delegation-cleanup-service.test.js.map +1 -0
  44. package/dist/services/agent-run-service.d.ts +44 -7
  45. package/dist/services/agent-run-service.d.ts.map +1 -1
  46. package/dist/services/agent-run-service.js +14 -0
  47. package/dist/services/agent-run-service.js.map +1 -1
  48. package/dist/services/agent-schedule-service.d.ts +21 -0
  49. package/dist/services/agent-schedule-service.d.ts.map +1 -1
  50. package/dist/services/agent-schedule-service.js +12 -0
  51. package/dist/services/agent-schedule-service.js.map +1 -1
  52. package/dist/services/audit-event-service.d.ts +76 -0
  53. package/dist/services/audit-event-service.d.ts.map +1 -0
  54. package/dist/services/audit-event-service.js +48 -0
  55. package/dist/services/audit-event-service.js.map +1 -0
  56. package/dist/services/delegation-cleanup-service.d.ts +133 -0
  57. package/dist/services/delegation-cleanup-service.d.ts.map +1 -0
  58. package/dist/services/delegation-cleanup-service.js +111 -0
  59. package/dist/services/delegation-cleanup-service.js.map +1 -0
  60. package/dist/services/edge-service.d.ts.map +1 -1
  61. package/dist/services/edge-service.js +3 -0
  62. package/dist/services/edge-service.js.map +1 -1
  63. package/dist/services/org-agent-type-service.d.ts +15 -0
  64. package/dist/services/org-agent-type-service.d.ts.map +1 -1
  65. package/dist/services/org-agent-type-service.js +2 -0
  66. package/dist/services/org-agent-type-service.js.map +1 -1
  67. package/dist/services/usage-service.d.ts +48 -0
  68. package/dist/services/usage-service.d.ts.map +1 -0
  69. package/dist/services/usage-service.js +116 -0
  70. package/dist/services/usage-service.js.map +1 -0
  71. package/dist/services/user-service.d.ts.map +1 -1
  72. package/dist/services/user-service.js +24 -6
  73. package/dist/services/user-service.js.map +1 -1
  74. package/dist/services/user-service.test.d.ts +2 -0
  75. package/dist/services/user-service.test.d.ts.map +1 -0
  76. package/dist/services/user-service.test.js +86 -0
  77. package/dist/services/user-service.test.js.map +1 -0
  78. package/dist/types/index.d.ts +13 -0
  79. package/dist/types/index.d.ts.map +1 -1
  80. package/package.json +3 -2
  81. package/prisma/schema.prisma +158 -82
  82. package/dist/db/schema.d.ts +0 -507
  83. package/dist/db/schema.d.ts.map +0 -1
  84. package/dist/db/schema.js +0 -77
  85. package/dist/db/schema.js.map +0 -1
package/dist/index.js CHANGED
@@ -7,6 +7,9 @@ export { encryptAesGcm, decryptAesGcm, deriveKey, deriveKeyV2 } from "./lib/cryp
7
7
  export { getAgentKeySecret, getPiiKeySecret, getEmbeddingKeySecret } from "./lib/encryption-keys.js";
8
8
  // JWT
9
9
  export { verifyAuth0Jwt } from "./lib/jwt.js";
10
+ export { isUserPrincipal, isOrgAgentPrincipal, isDelegatedAgentPrincipal, } from "./auth/principal.js";
11
+ export { buildAbility, intersect, UnsupportedIntersectionError, } from "./auth/ability.js";
12
+ export { DELEGATION_ALGORITHM, DELEGATION_ISSUER, DELEGATION_KEY_MIN_BYTES, DELEGATION_TTL_SECONDS, DelegationKeyLoadError, DelegationTokenError, loadDelegationKeyFromEnv, mintDelegationToken, peekIssuer, verifyDelegationToken, } from "./auth/delegation-jwt.js";
10
13
  // Types
11
14
  export * from "./types/index.js";
12
15
  // Config
@@ -27,11 +30,14 @@ export { OrgAgentConfigService } from "./services/org-agent-config-service.js";
27
30
  export { OrgAgentTypeService } from "./services/org-agent-type-service.js";
28
31
  export { OrgMcpServerService } from "./services/org-mcp-server-service.js";
29
32
  export { AgentRunService } from "./services/agent-run-service.js";
33
+ export { AuditEventService } from "./services/audit-event-service.js";
34
+ export { cancelOrphanedAgentRuns } from "./services/delegation-cleanup-service.js";
30
35
  export { AgentScheduleService } from "./services/agent-schedule-service.js";
31
36
  export { CLI_REFERENCE } from "./services/agent-cli-reference.js";
32
37
  export { UserService } from "./services/user-service.js";
33
38
  export { MembershipService } from "./services/membership-service.js";
34
39
  export { InviteService } from "./services/invite-service.js";
40
+ export { UsageService } from "./services/usage-service.js";
35
41
  // Providers
36
42
  export { createEmbeddingProvider, validateEmbeddingKey, OpenAIEmbeddingProvider, VoyageEmbeddingProvider, OllamaEmbeddingProvider } from "./providers/index.js";
37
43
  export { BatchingEmbeddingProvider } from "./providers/batching.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAEjE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAGvF,SAAS;AACT,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAErG,MAAM;AACN,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,QAAQ;AACR,cAAc,kBAAkB,CAAC;AAEjC,SAAS;AACT,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,WAAW;AACX,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEnE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4CAA4C,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAExE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAE5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAG3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAE/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAE3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAE3E,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAElE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAE5E,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAElE,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAErE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAG7D,YAAY;AACZ,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAEhK,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAEpE,OAAO,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEpG,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=jwt.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/jwt.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,97 @@
1
+ import { afterEach, describe, expect, it } from "vitest";
2
+ import { JWKS_CACHE_MAX_AGE_MS, JWKS_COOLDOWN_MS, createAuth0JwksResolver, resetJwksCache, verifyAuth0Jwt, } from "../jwt.js";
3
+ // A minimal JWKS response body. jose parses this on reload() but won't
4
+ // fail just because the keys are not usable for real verification —
5
+ // failure only happens when a JWT is actually verified against a key.
6
+ const FAKE_JWKS_BODY = JSON.stringify({
7
+ keys: [
8
+ {
9
+ kty: "RSA",
10
+ kid: "test-key-1",
11
+ use: "sig",
12
+ alg: "RS256",
13
+ n: "xGP_acGn7xCn3OQ0qoBXwOyw5nSGY3SnlbSXr3QxBOQPfOSmM0wQ4TgKGhY0t5T3pNS6EHF3OwBf3jL5p8O5_yQ",
14
+ e: "AQAB",
15
+ },
16
+ ],
17
+ });
18
+ function fakeJwksFetch(counter) {
19
+ return async (_url, _init) => {
20
+ counter.calls += 1;
21
+ return new Response(FAKE_JWKS_BODY, {
22
+ status: 200,
23
+ headers: { "content-type": "application/json" },
24
+ });
25
+ };
26
+ }
27
+ describe("JWKS bounded cache (finding M6)", () => {
28
+ afterEach(() => {
29
+ resetJwksCache();
30
+ });
31
+ it("publishes explicit cache bounds as source-visible constants", () => {
32
+ // The finding is that the JWKS cache has no visible invalidation.
33
+ // Closing it means the bounds live in our source, not in a library
34
+ // default that a future version bump could silently change.
35
+ expect(JWKS_CACHE_MAX_AGE_MS).toBe(5 * 60 * 1000);
36
+ expect(JWKS_COOLDOWN_MS).toBe(30 * 1000);
37
+ });
38
+ it("reload() on a fresh resolver triggers exactly one fetch", async () => {
39
+ const counter = { calls: 0 };
40
+ const resolver = createAuth0JwksResolver("example.auth0.com", {
41
+ cacheMaxAgeMs: 50,
42
+ cooldownMs: 0,
43
+ fetchImpl: fakeJwksFetch(counter),
44
+ });
45
+ await resolver.reload();
46
+ expect(counter.calls).toBe(1);
47
+ expect(resolver.fresh).toBe(true);
48
+ });
49
+ it("fresh becomes false after cacheMaxAge elapses", async () => {
50
+ const counter = { calls: 0 };
51
+ const resolver = createAuth0JwksResolver("example.auth0.com", {
52
+ cacheMaxAgeMs: 30,
53
+ cooldownMs: 0,
54
+ fetchImpl: fakeJwksFetch(counter),
55
+ });
56
+ await resolver.reload();
57
+ expect(resolver.fresh).toBe(true);
58
+ // Wait past cacheMaxAge. After this, jose's bounded-age check
59
+ // returns false, which is the signal that triggers automatic
60
+ // refetch on the next verification attempt.
61
+ await new Promise((r) => setTimeout(r, 60));
62
+ expect(resolver.fresh).toBe(false);
63
+ });
64
+ it("a second reload after cache expiry triggers a second fetch", async () => {
65
+ // The core M6 guarantee: a rotated/compromised signing key at
66
+ // Auth0 cannot stay trusted indefinitely. After cacheMaxAge
67
+ // elapses, jose re-fetches the JWKS — observable here via the
68
+ // mock fetch's call counter.
69
+ const counter = { calls: 0 };
70
+ const resolver = createAuth0JwksResolver("example.auth0.com", {
71
+ cacheMaxAgeMs: 20,
72
+ cooldownMs: 0,
73
+ fetchImpl: fakeJwksFetch(counter),
74
+ });
75
+ await resolver.reload();
76
+ expect(counter.calls).toBe(1);
77
+ await new Promise((r) => setTimeout(r, 40));
78
+ await resolver.reload();
79
+ expect(counter.calls).toBe(2);
80
+ });
81
+ });
82
+ describe("verifyAuth0Jwt", () => {
83
+ afterEach(() => {
84
+ resetJwksCache();
85
+ });
86
+ it("rejects a malformed token without touching the network", async () => {
87
+ // Sanity regression: verifyAuth0Jwt should fail fast on obviously
88
+ // invalid input. jose throws a parse error before any JWKS
89
+ // retrieval is attempted, so this is safe to run without
90
+ // mocking the network.
91
+ await expect(verifyAuth0Jwt("not-a-real-jwt", {
92
+ domain: "example.auth0.com",
93
+ audience: "https://api.example.com",
94
+ })).rejects.toThrow();
95
+ });
96
+ });
97
+ //# sourceMappingURL=jwt.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/jwt.test.ts"],"names":[],"mappings":"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"}
package/dist/lib/jwt.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { createRemoteJWKSet } from "jose";
1
2
  import type { JWTPayload } from "jose";
2
3
  export interface Auth0Config {
3
4
  domain: string;
@@ -6,8 +7,27 @@ export interface Auth0Config {
6
7
  export interface Auth0JwtPayload extends JWTPayload {
7
8
  sub: string;
8
9
  email?: string;
10
+ email_verified?: boolean;
9
11
  name?: string;
10
12
  org_id?: string;
11
13
  }
14
+ export declare const JWKS_CACHE_MAX_AGE_MS: number;
15
+ export declare const JWKS_COOLDOWN_MS: number;
16
+ export type JwksResolver = ReturnType<typeof createRemoteJWKSet>;
17
+ /**
18
+ * Build a remote JWKS resolver for an Auth0 domain with bounded caching.
19
+ * Exported for test injection; production callers use {@link getJWKS}.
20
+ */
21
+ export declare function createAuth0JwksResolver(domain: string, options?: {
22
+ cacheMaxAgeMs?: number;
23
+ cooldownMs?: number;
24
+ fetchImpl?: (url: URL | string, init?: RequestInit) => Promise<Response>;
25
+ }): JwksResolver;
26
+ /**
27
+ * Invalidate the per-process JWKS cache for a given Auth0 domain.
28
+ * Intended for tests and for manual revocation flows. Production auth
29
+ * flows rely on the bounded cacheMaxAge above to rotate keys.
30
+ */
31
+ export declare function resetJwksCache(domain?: string): void;
12
32
  export declare function verifyAuth0Jwt(token: string, config: Auth0Config): Promise<Auth0JwtPayload>;
13
33
  //# sourceMappingURL=jwt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/lib/jwt.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAEvC,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAaD,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,eAAe,CAAC,CAc1B"}
1
+ {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/lib/jwt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA0B,MAAM,MAAM,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAEvC,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAsBD,eAAO,MAAM,qBAAqB,QAAgB,CAAC;AACnD,eAAO,MAAM,gBAAgB,QAAY,CAAC;AAE1C,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAIjE;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IACR,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC1E,GACA,YAAY,CAcd;AAUD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAMpD;AAED,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,eAAe,CAAC,CAc1B"}
package/dist/lib/jwt.js CHANGED
@@ -1,13 +1,66 @@
1
- import { createRemoteJWKSet, jwtVerify } from "jose";
1
+ import { createRemoteJWKSet, customFetch, jwtVerify } from "jose";
2
+ // Bounded JWKS cache for Auth0 signing keys (closes finding M6).
3
+ //
4
+ // jose's createRemoteJWKSet has three relevant knobs: cooldownDuration
5
+ // (minimum gap between HTTP refetches triggered by kid misses),
6
+ // cacheMaxAge (maximum age before a refetch is mandatory regardless of
7
+ // kid state), and reload() (manual invalidation). We configure the
8
+ // first two explicitly so the security bounds are visible at the call
9
+ // site instead of inherited from whatever jose's defaults happen to be
10
+ // in the currently installed version.
11
+ //
12
+ // Exposure window for a compromised or rotated Auth0 signing key:
13
+ // - worst case ≤ JWKS_CACHE_MAX_AGE_MS (5 minutes) before jose
14
+ // force-refetches and drops the stale key from its internal cache.
15
+ // - best case: the next token Auth0 issues carries a kid not in
16
+ // cache, jose refetches immediately (subject to cooldown).
17
+ //
18
+ // We intentionally use a tighter cacheMaxAge than jose's 10-minute
19
+ // default because Auth0 key rotations and key compromises are both
20
+ // security-critical events where we'd rather hit jwks.json every few
21
+ // minutes than trust a stale key for longer.
22
+ export const JWKS_CACHE_MAX_AGE_MS = 5 * 60 * 1000;
23
+ export const JWKS_COOLDOWN_MS = 30 * 1000;
2
24
  const jwksCache = new Map();
25
+ /**
26
+ * Build a remote JWKS resolver for an Auth0 domain with bounded caching.
27
+ * Exported for test injection; production callers use {@link getJWKS}.
28
+ */
29
+ export function createAuth0JwksResolver(domain, options) {
30
+ const url = new URL(`https://${domain}/.well-known/jwks.json`);
31
+ const createOpts = {
32
+ cacheMaxAge: options?.cacheMaxAgeMs ?? JWKS_CACHE_MAX_AGE_MS,
33
+ cooldownDuration: options?.cooldownMs ?? JWKS_COOLDOWN_MS,
34
+ };
35
+ if (options?.fetchImpl) {
36
+ // jose exposes a named `customFetch` symbol for fetch injection;
37
+ // tests pass their mock in this way. Production callers never
38
+ // need it — the default fetch is used.
39
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
+ createOpts[customFetch] = options.fetchImpl;
41
+ }
42
+ return createRemoteJWKSet(url, createOpts);
43
+ }
3
44
  function getJWKS(domain) {
4
45
  const key = domain;
5
46
  if (!jwksCache.has(key)) {
6
- const url = new URL(`https://${domain}/.well-known/jwks.json`);
7
- jwksCache.set(key, createRemoteJWKSet(url));
47
+ jwksCache.set(key, createAuth0JwksResolver(domain));
8
48
  }
9
49
  return jwksCache.get(key);
10
50
  }
51
+ /**
52
+ * Invalidate the per-process JWKS cache for a given Auth0 domain.
53
+ * Intended for tests and for manual revocation flows. Production auth
54
+ * flows rely on the bounded cacheMaxAge above to rotate keys.
55
+ */
56
+ export function resetJwksCache(domain) {
57
+ if (domain) {
58
+ jwksCache.delete(domain);
59
+ }
60
+ else {
61
+ jwksCache.clear();
62
+ }
63
+ }
11
64
  export async function verifyAuth0Jwt(token, config) {
12
65
  const jwks = getJWKS(config.domain);
13
66
  const issuer = `https://${config.domain}/`;
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/lib/jwt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAerD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAiD,CAAC;AAE3E,SAAS,OAAO,CAAC,MAAc;IAC7B,MAAM,GAAG,GAAG,MAAM,CAAC;IACnB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,WAAW,MAAM,wBAAwB,CAAC,CAAC;QAC/D,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,SAAS,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAa,EACb,MAAmB;IAEnB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,WAAW,MAAM,CAAC,MAAM,GAAG,CAAC;IAE3C,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;QAC/C,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,MAAM;KACP,CAAC,CAAC;IAEH,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,OAA0B,CAAC;AACpC,CAAC"}
1
+ {"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/lib/jwt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAgBlE,iEAAiE;AACjE,EAAE;AACF,uEAAuE;AACvE,gEAAgE;AAChE,uEAAuE;AACvE,mEAAmE;AACnE,sEAAsE;AACtE,uEAAuE;AACvE,sCAAsC;AACtC,EAAE;AACF,kEAAkE;AAClE,iEAAiE;AACjE,uEAAuE;AACvE,kEAAkE;AAClE,+DAA+D;AAC/D,EAAE;AACF,mEAAmE;AACnE,mEAAmE;AACnE,qEAAqE;AACrE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AACnD,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,GAAG,IAAI,CAAC;AAI1C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAwB,CAAC;AAElD;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAc,EACd,OAIC;IAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,WAAW,MAAM,wBAAwB,CAAC,CAAC;IAC/D,MAAM,UAAU,GAA6C;QAC3D,WAAW,EAAE,OAAO,EAAE,aAAa,IAAI,qBAAqB;QAC5D,gBAAgB,EAAE,OAAO,EAAE,UAAU,IAAI,gBAAgB;KAC1D,CAAC;IACF,IAAI,OAAO,EAAE,SAAS,EAAE,CAAC;QACvB,iEAAiE;QACjE,8DAA8D;QAC9D,uCAAuC;QACvC,8DAA8D;QAC7D,UAAkB,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;IACvD,CAAC;IACD,OAAO,kBAAkB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,OAAO,CAAC,MAAc;IAC7B,MAAM,GAAG,GAAG,MAAM,CAAC;IACnB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,uBAAuB,CAAC,MAAM,CAAC,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,SAAS,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;AAC7B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,MAAe;IAC5C,IAAI,MAAM,EAAE,CAAC;QACX,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;SAAM,CAAC;QACN,SAAS,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAa,EACb,MAAmB;IAEnB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,WAAW,MAAM,CAAC,MAAM,GAAG,CAAC;IAE3C,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;QAC/C,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,MAAM;KACP,CAAC,CAAC;IAEH,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,OAA0B,CAAC;AACpC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=delegation-cleanup-service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegation-cleanup-service.test.d.ts","sourceRoot":"","sources":["../../../src/services/__tests__/delegation-cleanup-service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,211 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { cancelOrphanedAgentRuns, } from "../delegation-cleanup-service.js";
3
+ /**
4
+ * Tiny in-memory fake that satisfies `DelegationCleanupDb`. Uses the
5
+ * actual Prisma call shapes so the production call sites stay honest
6
+ * — if the real service ever changes its call arguments, these tests
7
+ * will catch it via the narrow interface. Audit writes are captured
8
+ * in-memory so tests can assert on their content.
9
+ */
10
+ function makeFakeDb(init) {
11
+ const auditCalls = [];
12
+ const updatedRuns = [];
13
+ const db = {
14
+ agentRun: {
15
+ findMany: vi.fn(async (_args) => init.pendingRuns.map((r) => ({
16
+ id: r.id,
17
+ organizationId: r.organizationId,
18
+ invokedByUserId: r.invokedByUserId,
19
+ }))),
20
+ updateMany: vi.fn(async (args) => {
21
+ if (init.failBulkUpdate) {
22
+ throw new Error("bulk update intentionally failing");
23
+ }
24
+ const ids = args.where.id.in;
25
+ updatedRuns.push(...ids);
26
+ return { count: ids.length };
27
+ }),
28
+ },
29
+ membership: {
30
+ findUnique: vi.fn(async (args) => {
31
+ const runId = [...init.pendingRuns]
32
+ .find((r) => r.invokedByUserId === args.where.userId_organizationId.userId &&
33
+ r.organizationId === args.where.userId_organizationId.organizationId)?.id;
34
+ if (runId && init.failMembershipLookup?.has(runId)) {
35
+ throw new Error(`membership lookup intentionally failing for ${runId}`);
36
+ }
37
+ const key = `${args.where.userId_organizationId.userId}:${args.where.userId_organizationId.organizationId}`;
38
+ return init.memberships.has(key) ? { id: `membership-${key}` } : null;
39
+ }),
40
+ },
41
+ auditEvent: {
42
+ create: vi.fn(async (args) => {
43
+ auditCalls.push(args.data);
44
+ return args.data;
45
+ }),
46
+ },
47
+ };
48
+ return { db, auditCalls, updatedRuns };
49
+ }
50
+ describe("cancelOrphanedAgentRuns", () => {
51
+ it("cancels runs whose invoking user has no membership in the org", async () => {
52
+ const { db, auditCalls, updatedRuns } = makeFakeDb({
53
+ pendingRuns: [
54
+ {
55
+ id: "run-1",
56
+ organizationId: "org-1",
57
+ invokedByUserId: "user-a",
58
+ status: "pending",
59
+ },
60
+ ],
61
+ memberships: new Set(), // user-a has no memberships
62
+ });
63
+ const result = await cancelOrphanedAgentRuns(db);
64
+ expect(result.scannedCount).toBe(1);
65
+ expect(result.cancelledRunIds).toEqual(["run-1"]);
66
+ expect(updatedRuns).toEqual(["run-1"]);
67
+ expect(auditCalls).toHaveLength(1);
68
+ expect(auditCalls[0]).toMatchObject({
69
+ agentRunId: "run-1",
70
+ action: "delegation.revoke",
71
+ result: "allow",
72
+ principalType: "system",
73
+ principalId: "delegation-cleanup",
74
+ });
75
+ });
76
+ it("leaves runs whose invoking user still has a membership", async () => {
77
+ const { db, updatedRuns, auditCalls } = makeFakeDb({
78
+ pendingRuns: [
79
+ {
80
+ id: "run-active",
81
+ organizationId: "org-1",
82
+ invokedByUserId: "user-a",
83
+ status: "running",
84
+ },
85
+ ],
86
+ memberships: new Set(["user-a:org-1"]),
87
+ });
88
+ const result = await cancelOrphanedAgentRuns(db);
89
+ expect(result.scannedCount).toBe(1);
90
+ expect(result.cancelledRunIds).toEqual([]);
91
+ expect(updatedRuns).toEqual([]);
92
+ expect(auditCalls).toEqual([]);
93
+ });
94
+ it("leaves runs whose invokedByUserId is null (API-key-authored)", async () => {
95
+ // findMany's WHERE already filters `invokedByUserId: not null`,
96
+ // so the fake wouldn't return these in practice — but the inner
97
+ // loop also has a belt-and-braces guard for `!run.invokedByUserId`
98
+ // and this test documents the intent.
99
+ const { db, updatedRuns } = makeFakeDb({
100
+ pendingRuns: [
101
+ {
102
+ id: "run-legacy",
103
+ organizationId: "org-1",
104
+ invokedByUserId: null,
105
+ status: "pending",
106
+ },
107
+ ],
108
+ memberships: new Set(),
109
+ });
110
+ const result = await cancelOrphanedAgentRuns(db);
111
+ expect(result.cancelledRunIds).toEqual([]);
112
+ expect(updatedRuns).toEqual([]);
113
+ });
114
+ it("processes a mix of orphaned and active runs in one sweep", async () => {
115
+ const { db, updatedRuns, auditCalls } = makeFakeDb({
116
+ pendingRuns: [
117
+ {
118
+ id: "run-orphan",
119
+ organizationId: "org-1",
120
+ invokedByUserId: "user-gone",
121
+ status: "pending",
122
+ },
123
+ {
124
+ id: "run-active",
125
+ organizationId: "org-1",
126
+ invokedByUserId: "user-still-here",
127
+ status: "running",
128
+ },
129
+ {
130
+ id: "run-orphan-other-org",
131
+ organizationId: "org-2",
132
+ invokedByUserId: "user-still-here",
133
+ status: "pending",
134
+ },
135
+ ],
136
+ memberships: new Set(["user-still-here:org-1"]),
137
+ });
138
+ const result = await cancelOrphanedAgentRuns(db);
139
+ expect(result.scannedCount).toBe(3);
140
+ expect(new Set(result.cancelledRunIds)).toEqual(new Set(["run-orphan", "run-orphan-other-org"]));
141
+ expect(new Set(updatedRuns)).toEqual(new Set(["run-orphan", "run-orphan-other-org"]));
142
+ expect(auditCalls).toHaveLength(2);
143
+ const auditedIds = auditCalls.map((a) => a.agentRunId).sort();
144
+ expect(auditedIds).toEqual(["run-orphan", "run-orphan-other-org"]);
145
+ });
146
+ it("continues the sweep when an individual membership lookup throws", async () => {
147
+ const { db, updatedRuns } = makeFakeDb({
148
+ pendingRuns: [
149
+ {
150
+ id: "run-bad",
151
+ organizationId: "org-1",
152
+ invokedByUserId: "user-bad",
153
+ status: "pending",
154
+ },
155
+ {
156
+ id: "run-good",
157
+ organizationId: "org-1",
158
+ invokedByUserId: "user-gone",
159
+ status: "pending",
160
+ },
161
+ ],
162
+ memberships: new Set(),
163
+ failMembershipLookup: new Set(["run-bad"]),
164
+ });
165
+ // Suppress the expected console.error from the sweep's catch block.
166
+ const consoleErrorSpy = vi
167
+ .spyOn(console, "error")
168
+ .mockImplementation(() => { });
169
+ const result = await cancelOrphanedAgentRuns(db);
170
+ consoleErrorSpy.mockRestore();
171
+ // run-bad was skipped (lookup threw) and run-good was cancelled.
172
+ // scannedCount still reflects both because the sweep read both.
173
+ expect(result.scannedCount).toBe(2);
174
+ expect(result.cancelledRunIds).toEqual(["run-good"]);
175
+ expect(updatedRuns).toEqual(["run-good"]);
176
+ });
177
+ it("returns empty cancelledRunIds when the bulk update fails", async () => {
178
+ const { db, updatedRuns, auditCalls } = makeFakeDb({
179
+ pendingRuns: [
180
+ {
181
+ id: "run-1",
182
+ organizationId: "org-1",
183
+ invokedByUserId: "user-a",
184
+ status: "pending",
185
+ },
186
+ ],
187
+ memberships: new Set(),
188
+ failBulkUpdate: true,
189
+ });
190
+ const consoleErrorSpy = vi
191
+ .spyOn(console, "error")
192
+ .mockImplementation(() => { });
193
+ const result = await cancelOrphanedAgentRuns(db);
194
+ consoleErrorSpy.mockRestore();
195
+ expect(result.cancelledRunIds).toEqual([]);
196
+ expect(updatedRuns).toEqual([]);
197
+ // No audit events because no runs successfully transitioned.
198
+ expect(auditCalls).toEqual([]);
199
+ });
200
+ it("is a no-op when there are no pending runs at all", async () => {
201
+ const { db, updatedRuns, auditCalls } = makeFakeDb({
202
+ pendingRuns: [],
203
+ memberships: new Set(),
204
+ });
205
+ const result = await cancelOrphanedAgentRuns(db);
206
+ expect(result).toEqual({ scannedCount: 0, cancelledRunIds: [] });
207
+ expect(updatedRuns).toEqual([]);
208
+ expect(auditCalls).toEqual([]);
209
+ });
210
+ });
211
+ //# sourceMappingURL=delegation-cleanup-service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegation-cleanup-service.test.js","sourceRoot":"","sources":["../../../src/services/__tests__/delegation-cleanup-service.test.ts"],"names":[],"mappings":"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"}
@@ -12,17 +12,54 @@ export interface AgentRun {
12
12
  completedAt: Date | null;
13
13
  createdBy: string;
14
14
  scheduleId: string | null;
15
+ /**
16
+ * FK to `OrgAgentType.id`. Populated by the Phase 1d spawn path for
17
+ * runs whose agent type resolves to a DB-backed row. Built-in agent
18
+ * types that have no org-level row stay `null`.
19
+ */
20
+ agentId: string | null;
21
+ /**
22
+ * FK to `User.id`. Populated by the Phase 1d spawn path whenever a
23
+ * run is spawned from a user-authenticated request. API-key-authored
24
+ * runs stay `null` because there is no owning user.
25
+ */
26
+ invokedByUserId: string | null;
27
+ /**
28
+ * The intersected rule set captured at spawn time (Phase 1d). The
29
+ * middleware rehydrates this into a `DelegatedAgentPrincipal` ability
30
+ * on every sandbox callback — see `buildAbility` in core/auth. Stored
31
+ * as `Json?`; surfaced here as `unknown` so callers must narrow it
32
+ * before use.
33
+ */
34
+ capturedAbility: unknown;
35
+ }
36
+ export interface AgentRunCreateInput {
37
+ prompt: string;
38
+ type?: string;
39
+ model: string;
40
+ createdBy: string;
41
+ scheduleId?: string;
42
+ /**
43
+ * FK to `OrgAgentType.id` — only set when the agent type is a DB-
44
+ * backed row. Built-in types without an org override leave this unset.
45
+ */
46
+ agentId?: string | null;
47
+ /**
48
+ * FK to `User.id` — only set for user-authenticated spawn paths.
49
+ */
50
+ invokedByUserId?: string | null;
51
+ /**
52
+ * The captured CASL rule set, i.e. `intersect(userAbility,
53
+ * orgAgentType.intrinsicPolicy)`. Only set for user-authenticated
54
+ * spawn paths. API-key-authored runs leave this null and the legacy
55
+ * `OrgAgentPrincipal` path in the middleware grants `manage all`.
56
+ */
57
+ capturedAbility?: unknown;
15
58
  }
16
59
  export declare class AgentRunService {
17
60
  private db;
18
61
  constructor(db: PrismaClient);
19
- create(organizationId: string, input: {
20
- prompt: string;
21
- type?: string;
22
- model: string;
23
- createdBy: string;
24
- scheduleId?: string;
25
- }): Promise<AgentRun>;
62
+ create(organizationId: string, input: AgentRunCreateInput): Promise<AgentRun>;
26
63
  updateStatus(id: string, organizationId: string, update: {
27
64
  status: string;
28
65
  result?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-run-service.d.ts","sourceRoot":"","sources":["../../src/services/agent-run-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,qBAAa,eAAe;IACd,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,YAAY;IAE9B,MAAM,CACV,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9F,OAAO,CAAC,QAAQ,CAAC;IAed,YAAY,CAChB,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,IAAI,CAAC;KACpB,GACA,OAAO,CAAC,QAAQ,CAAC;IAcd,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAQrE,IAAI,CACR,cAAc,EAAE,MAAM,EACtB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GACxD,OAAO,CAAC,QAAQ,EAAE,CAAC;IAatB,OAAO,CAAC,UAAU;CAgBnB"}
1
+ {"version":3,"file":"agent-run-service.d.ts","sourceRoot":"","sources":["../../src/services/agent-run-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;OAIG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;;OAIG;IACH,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;;;OAMG;IACH,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,qBAAa,eAAe;IACd,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,YAAY;IAE9B,MAAM,CACV,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,QAAQ,CAAC;IA2Bd,YAAY,CAChB,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,IAAI,CAAC;KACpB,GACA,OAAO,CAAC,QAAQ,CAAC;IAcd,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAQrE,IAAI,CACR,cAAc,EAAE,MAAM,EACtB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GACxD,OAAO,CAAC,QAAQ,EAAE,CAAC;IAatB,OAAO,CAAC,UAAU;CAmBnB"}
@@ -13,6 +13,17 @@ export class AgentRunService {
13
13
  status: "pending",
14
14
  createdBy: input.createdBy,
15
15
  scheduleId: input.scheduleId ?? null,
16
+ agentId: input.agentId ?? null,
17
+ invokedByUserId: input.invokedByUserId ?? null,
18
+ // Prisma's typed `Json?` wants `undefined` to leave the column
19
+ // as its default (null) and a concrete object/array to write a
20
+ // value. `null` and `undefined` both collapse to "don't write
21
+ // anything" here; API-key spawn paths leave this unset and the
22
+ // resulting row has capturedAbility = null, which is the correct
23
+ // shape for legacy runs.
24
+ capturedAbility: input.capturedAbility == null
25
+ ? undefined
26
+ : input.capturedAbility,
16
27
  },
17
28
  });
18
29
  return this.toAgentRun(run);
@@ -64,6 +75,9 @@ export class AgentRunService {
64
75
  completedAt: run.completedAt,
65
76
  createdBy: run.createdBy,
66
77
  scheduleId: run.scheduleId,
78
+ agentId: run.agentId ?? null,
79
+ invokedByUserId: run.invokedByUserId ?? null,
80
+ capturedAbility: run.capturedAbility ?? null,
67
81
  };
68
82
  }
69
83
  }
@@ -1 +1 @@
1
- {"version":3,"file":"agent-run-service.js","sourceRoot":"","sources":["../../src/services/agent-run-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-run-service.js","sourceRoot":"","sources":["../../src/services/agent-run-service.ts"],"names":[],"mappings":"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"}