@app-vitals/agent-admin 0.13.0 → 0.13.2

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 (41) hide show
  1. package/e2e/test-server.ts +5 -5
  2. package/openapi.json +12 -19
  3. package/openapi.platform.json +11 -18
  4. package/package.json +2 -2
  5. package/prisma/client/internal/class.ts +4 -4
  6. package/prisma/client/internal/prismaNamespace.ts +0 -1
  7. package/prisma/client/internal/prismaNamespaceBrowser.ts +0 -1
  8. package/prisma/client/models/Agent.ts +62 -137
  9. package/prisma/migrations/20261030000000_drop_agent_type_name/migration.sql +8 -0
  10. package/prisma/schema/schema.prisma +3 -4
  11. package/src/account-lifecycle.integration.test.ts +1 -1
  12. package/src/account-trial-warning-sweeper.integration.test.ts +1 -1
  13. package/src/admin-local-agent.smoke.test.ts +12 -12
  14. package/src/admin-ui-pages.ts +2 -2
  15. package/src/admin-ui-pages.unit.test.ts +2 -2
  16. package/src/admin-ui.fixtures.ts +6 -6
  17. package/src/admin-ui.smoke.test.ts +39 -39
  18. package/src/admin-ui.ts +8 -8
  19. package/src/agent-cron-jobs.integration.test.ts +8 -7
  20. package/src/agent-cron-jobs.ts +4 -5
  21. package/src/agent-cron-jobs.unit.test.ts +23 -23
  22. package/src/agent-patch-author-allowlist.integration.test.ts +4 -4
  23. package/src/agent-specialty-backfill.integration.test.ts +98 -53
  24. package/src/agents-api.integration.test.ts +20 -20
  25. package/src/agents-api.smoke.test.ts +76 -77
  26. package/src/agents-api.ts +9 -14
  27. package/src/agents.integration.test.ts +40 -53
  28. package/src/agents.ts +33 -46
  29. package/src/agents.unit.test.ts +28 -35
  30. package/src/api.smoke.test.ts +24 -2
  31. package/src/api.ts +15 -16
  32. package/src/openapi-schemas.ts +14 -7
  33. package/src/slack-provisioning-service.integration.test.ts +2 -2
  34. package/src/slack-provisioning.integration.test.ts +2 -2
  35. package/src/specialty-manifest-loader.ts +32 -32
  36. package/src/specialty-manifest-loader.unit.test.ts +8 -8
  37. package/src/startup-policy-reconcile.unit.test.ts +1 -1
  38. package/src/trial-expiry-sweeper.integration.test.ts +1 -1
  39. package/src/trial-expiry-warning-sweeper.integration.test.ts +1 -1
  40. package/src/agent-specialty.ts +0 -22
  41. package/src/agent-specialty.unit.test.ts +0 -43
@@ -28,7 +28,7 @@ import { identityCrypto } from "./token-crypto.ts";
28
28
  // ─── Fake SpecialtyManifestResolver ────────────────────────────────────────
29
29
  //
30
30
  // Mirrors the shape used by agent-cron-jobs.unit.test.ts's fakeRegistry —
31
- // resolves a fixed set of manifests by typeName, with tryGetManifest()
31
+ // resolves a fixed set of manifests by specialty, with tryGetManifest()
32
32
  // returning undefined (no fallback) for anything not in the map.
33
33
 
34
34
  const CODING_MANIFEST: SpecialtyManifest = {
@@ -72,11 +72,11 @@ function fakeSpecialtyRegistry(
72
72
  },
73
73
  ): AdminDeps["specialtyRegistry"] {
74
74
  return {
75
- getManifest(typeName: string) {
76
- return byType[typeName] ?? (byType.coding as SpecialtyManifest);
75
+ getManifest(specialty: string) {
76
+ return byType[specialty] ?? (byType.coding as SpecialtyManifest);
77
77
  },
78
- tryGetManifest(typeName: string) {
79
- return byType[typeName];
78
+ tryGetManifest(specialty: string) {
79
+ return byType[specialty];
80
80
  },
81
81
  listTypes() {
82
82
  return Object.entries(byType).map(([name, manifest]) => ({
@@ -240,7 +240,7 @@ function makeMockDeps(): AdminDeps {
240
240
  reviewAuthorAllowlist: [],
241
241
  patchAuthorAllowlist: [],
242
242
  restrictSlackToMembers: input.restrictSlackToMembers ?? false,
243
- typeName: "coding",
243
+ specialty: "coding",
244
244
  createdAt: new Date("2024-01-01"),
245
245
  updatedAt: new Date("2024-01-01"),
246
246
  missingRequiredEnv: [],
@@ -251,13 +251,13 @@ function makeMockDeps(): AdminDeps {
251
251
  id: AGENT_ID,
252
252
  name: "Existing Agent",
253
253
  selfHosted: false,
254
- typeName: "coding",
254
+ specialty: "coding",
255
255
  },
256
256
  {
257
257
  id: "agent-other-id",
258
258
  name: "Other Agent",
259
259
  selfHosted: false,
260
- typeName: "coding",
260
+ specialty: "coding",
261
261
  },
262
262
  ],
263
263
  getSummary: async (id: string) =>
@@ -266,7 +266,7 @@ function makeMockDeps(): AdminDeps {
266
266
  id: AGENT_ID,
267
267
  name: "Existing Agent",
268
268
  selfHosted: false,
269
- typeName: "coding",
269
+ specialty: "coding",
270
270
  }
271
271
  : null,
272
272
  getDetail: async (id: string) =>
@@ -280,7 +280,7 @@ function makeMockDeps(): AdminDeps {
280
280
  reviewAuthorAllowlist: [],
281
281
  patchAuthorAllowlist: [],
282
282
  restrictSlackToMembers: false,
283
- typeName: "coding",
283
+ specialty: "coding",
284
284
  createdAt: new Date("2024-01-01"),
285
285
  updatedAt: new Date("2024-01-01"),
286
286
  missingRequiredEnv: [],
@@ -312,7 +312,7 @@ function makeMockDeps(): AdminDeps {
312
312
  reviewAuthorAllowlist: [],
313
313
  patchAuthorAllowlist: [],
314
314
  restrictSlackToMembers: input.restrictSlackToMembers ?? false,
315
- typeName: "coding",
315
+ specialty: "coding",
316
316
  createdAt: new Date("2024-01-01"),
317
317
  updatedAt: new Date("2024-01-01"),
318
318
  missingRequiredEnv: [],
@@ -343,7 +343,7 @@ function makeMockDeps(): AdminDeps {
343
343
  reviewAuthorAllowlist: input.reviewAuthorAllowlist ?? [],
344
344
  patchAuthorAllowlist: input.patchAuthorAllowlist ?? [],
345
345
  restrictSlackToMembers: input.restrictSlackToMembers ?? false,
346
- typeName: "coding",
346
+ specialty: "coding",
347
347
  createdAt: new Date("2024-01-01"),
348
348
  updatedAt: new Date("2024-01-01"),
349
349
  missingRequiredEnv: [],
@@ -1651,7 +1651,7 @@ describe("admin API — POST /agents", () => {
1651
1651
  const app = createAdminApp(deps);
1652
1652
  const res = await app.request("/agents", {
1653
1653
  method: "POST",
1654
- body: JSON.stringify({ name: "New Agent", typeName: "coding" }),
1654
+ body: JSON.stringify({ name: "New Agent", specialty: "coding" }),
1655
1655
  headers: {
1656
1656
  "Content-Type": "application/json",
1657
1657
  Authorization: `Bearer ${ADMIN_API_KEY}`,
@@ -1669,7 +1669,7 @@ describe("admin API — POST /agents", () => {
1669
1669
  reviewAuthorAllowlist: [],
1670
1670
  patchAuthorAllowlist: [],
1671
1671
  restrictSlackToMembers: false,
1672
- typeName: "coding",
1672
+ specialty: "coding",
1673
1673
  missingRequiredEnv: [],
1674
1674
  });
1675
1675
  expect(typeof body.createdAt).toBe("string");
@@ -1680,7 +1680,7 @@ describe("admin API — POST /agents", () => {
1680
1680
  const app = createAdminApp(makeMockDeps());
1681
1681
  const res = await app.request("/agents", {
1682
1682
  method: "POST",
1683
- body: JSON.stringify({ name: "Cookie Agent", typeName: "coding" }),
1683
+ body: JSON.stringify({ name: "Cookie Agent", specialty: "coding" }),
1684
1684
  headers: {
1685
1685
  "Content-Type": "application/json",
1686
1686
  Cookie: `admin_session=${cookie}`,
@@ -1717,7 +1717,7 @@ describe("admin API — POST /agents", () => {
1717
1717
  const app = createAdminApp(deps);
1718
1718
  const res = await app.request("/agents", {
1719
1719
  method: "POST",
1720
- body: JSON.stringify({ name: "Owned Agent", typeName: "coding" }),
1720
+ body: JSON.stringify({ name: "Owned Agent", specialty: "coding" }),
1721
1721
  headers: {
1722
1722
  "Content-Type": "application/json",
1723
1723
  Cookie: `admin_session=${cookie}`,
@@ -1735,7 +1735,7 @@ describe("admin API — POST /agents", () => {
1735
1735
  method: "POST",
1736
1736
  body: JSON.stringify({
1737
1737
  name: "Spoof Agent",
1738
- typeName: "coding",
1738
+ specialty: "coding",
1739
1739
  ownerEmail: "attacker@evil.example",
1740
1740
  }),
1741
1741
  headers: {
@@ -1755,7 +1755,7 @@ describe("admin API — POST /agents", () => {
1755
1755
  method: "POST",
1756
1756
  body: JSON.stringify({
1757
1757
  name: "Key Agent",
1758
- typeName: "coding",
1758
+ specialty: "coding",
1759
1759
  ownerEmail: "attacker@evil.example",
1760
1760
  }),
1761
1761
  headers: {
@@ -1775,7 +1775,7 @@ describe("admin API — POST /agents", () => {
1775
1775
  const app = createAdminApp(deps);
1776
1776
  const res = await app.request("/agents", {
1777
1777
  method: "POST",
1778
- body: JSON.stringify({ name: "Ops Agent", typeName: "coding" }),
1778
+ body: JSON.stringify({ name: "Ops Agent", specialty: "coding" }),
1779
1779
  headers: {
1780
1780
  "Content-Type": "application/json",
1781
1781
  Authorization: `Bearer ${ADMIN_API_KEY}`,
@@ -1791,7 +1791,7 @@ describe("admin API — POST /agents", () => {
1791
1791
  method: "POST",
1792
1792
  body: JSON.stringify({
1793
1793
  name: "Collider",
1794
- typeName: "coding",
1794
+ specialty: "coding",
1795
1795
  reposRaw: "acme/api\nglobex/api",
1796
1796
  }),
1797
1797
  headers: {
@@ -1809,7 +1809,7 @@ describe("admin API — POST /agents", () => {
1809
1809
  const app = createAdminApp(makeMockDeps());
1810
1810
  const res = await app.request("/agents", {
1811
1811
  method: "POST",
1812
- body: JSON.stringify({ name: "New Agent", typeName: "coding" }),
1812
+ body: JSON.stringify({ name: "New Agent", specialty: "coding" }),
1813
1813
  headers: { "Content-Type": "application/json" },
1814
1814
  });
1815
1815
  expect(res.status).toBe(401);
@@ -1832,7 +1832,7 @@ describe("admin API — POST /agents", () => {
1832
1832
  const app = createAdminApp(deps);
1833
1833
  const res = await app.request("/agents", {
1834
1834
  method: "POST",
1835
- body: JSON.stringify({ name: "New Agent", typeName: "coding" }),
1835
+ body: JSON.stringify({ name: "New Agent", specialty: "coding" }),
1836
1836
  headers: {
1837
1837
  "Content-Type": "application/json",
1838
1838
  Authorization: "Bearer not-a-real-key",
@@ -1853,7 +1853,7 @@ describe("admin API — POST /agents", () => {
1853
1853
  const app = createAdminApp(deps);
1854
1854
  const res = await app.request("/agents", {
1855
1855
  method: "POST",
1856
- body: JSON.stringify({ name: "New Agent", typeName: "coding" }),
1856
+ body: JSON.stringify({ name: "New Agent", specialty: "coding" }),
1857
1857
  headers: {
1858
1858
  "Content-Type": "application/json",
1859
1859
  Authorization: "Bearer per-agent-token",
@@ -1867,7 +1867,7 @@ describe("admin API — POST /agents", () => {
1867
1867
  const app = createAdminApp(deps);
1868
1868
  const res = await app.request("/agents", {
1869
1869
  method: "POST",
1870
- body: JSON.stringify({ typeName: "coding" }),
1870
+ body: JSON.stringify({ specialty: "coding" }),
1871
1871
  headers: {
1872
1872
  "Content-Type": "application/json",
1873
1873
  Authorization: `Bearer ${ADMIN_API_KEY}`,
@@ -1878,12 +1878,12 @@ describe("admin API — POST /agents", () => {
1878
1878
  expect(createCalls()).toBe(0);
1879
1879
  });
1880
1880
 
1881
- it("unresolvable typeName → 4xx and no Agent row created", async () => {
1881
+ it("unresolvable specialty → 4xx and no Agent row created", async () => {
1882
1882
  const { deps, createCalls } = makeMockDepsCountingCreateCalls();
1883
1883
  const app = createAdminApp(deps);
1884
1884
  const res = await app.request("/agents", {
1885
1885
  method: "POST",
1886
- body: JSON.stringify({ name: "New Agent", typeName: "no-such-type" }),
1886
+ body: JSON.stringify({ name: "New Agent", specialty: "no-such-type" }),
1887
1887
  headers: {
1888
1888
  "Content-Type": "application/json",
1889
1889
  Authorization: `Bearer ${ADMIN_API_KEY}`,
@@ -1997,7 +1997,7 @@ describe("admin API — delete agent", () => {
1997
1997
  reviewAuthorAllowlist: [],
1998
1998
  patchAuthorAllowlist: [],
1999
1999
  restrictSlackToMembers: false,
2000
- typeName: "coding",
2000
+ specialty: "coding",
2001
2001
  createdAt: new Date("2024-01-01"),
2002
2002
  updatedAt: new Date("2024-01-01"),
2003
2003
  missingRequiredEnv: [],
@@ -2262,7 +2262,7 @@ describe("admin API — POST /agents/reconcile", () => {
2262
2262
  id: AGENT_ID,
2263
2263
  name: "Regular Agent",
2264
2264
  selfHosted: false,
2265
- typeName: "coding",
2265
+ specialty: "coding",
2266
2266
  ownerEmail: "jane.doe@example.com",
2267
2267
  anthropicIdentityName: null,
2268
2268
  anthropicServiceAccountId: null,
@@ -2348,7 +2348,6 @@ describe("admin API — POST /agents/reconcile", () => {
2348
2348
  id: AGENT_ID,
2349
2349
  name: "Regular Agent",
2350
2350
  selfHosted: false,
2351
- typeName: "coding",
2352
2351
  specialty: "coding",
2353
2352
  });
2354
2353
  });
@@ -2378,7 +2377,7 @@ function makeStripDeps(): {
2378
2377
  id,
2379
2378
  name: id,
2380
2379
  selfHosted,
2381
- typeName: "coding",
2380
+ specialty: "coding",
2382
2381
  });
2383
2382
  const deps: AdminDeps = {
2384
2383
  ...base,
@@ -2688,7 +2687,7 @@ describe("admin API — provision agent", () => {
2688
2687
  id: AGENT_ID,
2689
2688
  name: "Self-Hosted Agent",
2690
2689
  selfHosted: true,
2691
- typeName: "coding",
2690
+ specialty: "coding",
2692
2691
  }
2693
2692
  : null,
2694
2693
  },
@@ -2725,13 +2724,13 @@ describe("admin API — selfHosted field", () => {
2725
2724
  id: AGENT_ID,
2726
2725
  name: "Existing Agent",
2727
2726
  selfHosted: false,
2728
- typeName: "coding",
2727
+ specialty: "coding",
2729
2728
  },
2730
2729
  {
2731
2730
  id: "agent-other-id",
2732
2731
  name: "Other Agent",
2733
2732
  selfHosted: true,
2734
- typeName: "coding",
2733
+ specialty: "coding",
2735
2734
  },
2736
2735
  ],
2737
2736
  },
@@ -2863,13 +2862,13 @@ describe("admin API — selfHosted field", () => {
2863
2862
  id: AGENT_ID,
2864
2863
  name: "Regular Agent",
2865
2864
  selfHosted: false,
2866
- typeName: "coding",
2865
+ specialty: "coding",
2867
2866
  },
2868
2867
  {
2869
2868
  id: "self-hosted-id",
2870
2869
  name: "Self-Hosted Agent",
2871
2870
  selfHosted: true,
2872
- typeName: "coding",
2871
+ specialty: "coding",
2873
2872
  },
2874
2873
  ],
2875
2874
  },
@@ -3087,7 +3086,7 @@ describe("admin API — owner and Anthropic identity fields (PAI-2.5)", () => {
3087
3086
  reviewAuthorAllowlist: [],
3088
3087
  patchAuthorAllowlist: [],
3089
3088
  restrictSlackToMembers: false,
3090
- typeName: "coding",
3089
+ specialty: "coding",
3091
3090
  createdAt: new Date("2024-01-01"),
3092
3091
  updatedAt: new Date("2024-01-01"),
3093
3092
  missingRequiredEnv: [],
@@ -3149,7 +3148,7 @@ describe("admin API — owner and Anthropic identity fields (PAI-2.5)", () => {
3149
3148
  id: AGENT_ID,
3150
3149
  name: "Existing Agent",
3151
3150
  selfHosted: false,
3152
- typeName: "coding",
3151
+ specialty: "coding",
3153
3152
  ownerEmail: "jane.doe@example.com",
3154
3153
  anthropicIdentityName: "shipwright-existing-agent",
3155
3154
  anthropicServiceAccountId: "svac_01ABC",
@@ -3169,16 +3168,16 @@ describe("admin API — owner and Anthropic identity fields (PAI-2.5)", () => {
3169
3168
  });
3170
3169
  });
3171
3170
 
3172
- // ─── typeName field smoke tests ───────────────────────────────────────────────
3171
+ // ─── specialty field smoke tests ───────────────────────────────────────────────
3173
3172
 
3174
- describe("admin API — typeName field", () => {
3173
+ describe("admin API — specialty field", () => {
3175
3174
  let cookie: string;
3176
3175
 
3177
3176
  beforeAll(async () => {
3178
3177
  cookie = await makeSessionCookie();
3179
3178
  });
3180
3179
 
3181
- it("GET /agents includes typeName in each list entry", async () => {
3180
+ it("GET /agents includes specialty in each list entry", async () => {
3182
3181
  const app = createAdminApp(makeMockDeps());
3183
3182
  const res = await app.request("/agents", {
3184
3183
  headers: { Cookie: `admin_session=${cookie}` },
@@ -3186,17 +3185,17 @@ describe("admin API — typeName field", () => {
3186
3185
  expect(res.status).toBe(200);
3187
3186
  const body = await res.json();
3188
3187
  expect(Array.isArray(body)).toBe(true);
3189
- expect(body[0].typeName).toBe("coding");
3188
+ expect(body[0].specialty).toBe("coding");
3190
3189
  });
3191
3190
 
3192
- it("GET /agents/:id includes typeName in the full record", async () => {
3191
+ it("GET /agents/:id includes specialty in the full record", async () => {
3193
3192
  const app = createAdminApp(makeMockDeps());
3194
3193
  const res = await app.request(`/agents/${AGENT_ID}`, {
3195
3194
  headers: { Cookie: `admin_session=${cookie}` },
3196
3195
  });
3197
3196
  expect(res.status).toBe(200);
3198
3197
  const body = await res.json();
3199
- expect(body.typeName).toBe("coding");
3198
+ expect(body.specialty).toBe("coding");
3200
3199
  });
3201
3200
 
3202
3201
  it.each([
@@ -3260,7 +3259,7 @@ describe("admin API — missingRequiredEnv field", () => {
3260
3259
  reviewAuthorAllowlist: [],
3261
3260
  patchAuthorAllowlist: [],
3262
3261
  restrictSlackToMembers: false,
3263
- typeName: "coding",
3262
+ specialty: "coding",
3264
3263
  createdAt: new Date("2024-01-01"),
3265
3264
  updatedAt: new Date("2024-01-01"),
3266
3265
  missingRequiredEnv: ["CLAUDE_CODE_OAUTH_TOKEN"],
@@ -3331,7 +3330,7 @@ describe("admin API — repos field", () => {
3331
3330
  reviewAuthorAllowlist: [],
3332
3331
  patchAuthorAllowlist: [],
3333
3332
  restrictSlackToMembers: false,
3334
- typeName: "coding",
3333
+ specialty: "coding",
3335
3334
  createdAt: new Date("2024-01-01"),
3336
3335
  updatedAt: new Date("2024-01-01"),
3337
3336
  missingRequiredEnv: [],
@@ -3349,7 +3348,7 @@ describe("admin API — repos field", () => {
3349
3348
  reviewAuthorAllowlist: [],
3350
3349
  patchAuthorAllowlist: [],
3351
3350
  restrictSlackToMembers: false,
3352
- typeName: "coding",
3351
+ specialty: "coding",
3353
3352
  createdAt: new Date("2024-01-01"),
3354
3353
  updatedAt: new Date("2024-01-01"),
3355
3354
  missingRequiredEnv: [],
@@ -3387,7 +3386,7 @@ describe("admin API — repos field", () => {
3387
3386
  reviewAuthorAllowlist: [],
3388
3387
  patchAuthorAllowlist: [],
3389
3388
  restrictSlackToMembers: false,
3390
- typeName: "coding",
3389
+ specialty: "coding",
3391
3390
  createdAt: new Date("2024-01-01"),
3392
3391
  updatedAt: new Date("2024-01-01"),
3393
3392
  missingRequiredEnv: [],
@@ -3405,7 +3404,7 @@ describe("admin API — repos field", () => {
3405
3404
  reviewAuthorAllowlist: [],
3406
3405
  patchAuthorAllowlist: [],
3407
3406
  restrictSlackToMembers: false,
3408
- typeName: "coding",
3407
+ specialty: "coding",
3409
3408
  createdAt: new Date("2024-01-01"),
3410
3409
  updatedAt: new Date("2024-01-01"),
3411
3410
  missingRequiredEnv: [],
@@ -3481,7 +3480,7 @@ describe("admin API — reviewAuthorAllowlist field", () => {
3481
3480
  reviewAuthorAllowlist: [],
3482
3481
  patchAuthorAllowlist: [],
3483
3482
  restrictSlackToMembers: false,
3484
- typeName: "coding",
3483
+ specialty: "coding",
3485
3484
  createdAt: new Date("2024-01-01"),
3486
3485
  updatedAt: new Date("2024-01-01"),
3487
3486
  missingRequiredEnv: [],
@@ -3503,7 +3502,7 @@ describe("admin API — reviewAuthorAllowlist field", () => {
3503
3502
  reviewAuthorAllowlist: input.reviewAuthorAllowlist ?? [],
3504
3503
  patchAuthorAllowlist: [],
3505
3504
  restrictSlackToMembers: false,
3506
- typeName: "coding",
3505
+ specialty: "coding",
3507
3506
  createdAt: new Date("2024-01-01"),
3508
3507
  updatedAt: new Date("2024-01-01"),
3509
3508
  missingRequiredEnv: [],
@@ -3541,7 +3540,7 @@ describe("admin API — reviewAuthorAllowlist field", () => {
3541
3540
  reviewAuthorAllowlist: ["octocat"],
3542
3541
  patchAuthorAllowlist: [],
3543
3542
  restrictSlackToMembers: false,
3544
- typeName: "coding",
3543
+ specialty: "coding",
3545
3544
  createdAt: new Date("2024-01-01"),
3546
3545
  updatedAt: new Date("2024-01-01"),
3547
3546
  missingRequiredEnv: [],
@@ -3563,7 +3562,7 @@ describe("admin API — reviewAuthorAllowlist field", () => {
3563
3562
  reviewAuthorAllowlist: input.reviewAuthorAllowlist ?? [],
3564
3563
  patchAuthorAllowlist: [],
3565
3564
  restrictSlackToMembers: false,
3566
- typeName: "coding",
3565
+ specialty: "coding",
3567
3566
  createdAt: new Date("2024-01-01"),
3568
3567
  updatedAt: new Date("2024-01-01"),
3569
3568
  missingRequiredEnv: [],
@@ -3624,7 +3623,7 @@ describe("admin API — reviewAuthorAllowlist field", () => {
3624
3623
  reviewAuthorAllowlist: [],
3625
3624
  patchAuthorAllowlist: [],
3626
3625
  restrictSlackToMembers: false,
3627
- typeName: "coding",
3626
+ specialty: "coding",
3628
3627
  createdAt: new Date("2024-01-01"),
3629
3628
  updatedAt: new Date("2024-01-01"),
3630
3629
  missingRequiredEnv: [],
@@ -3642,7 +3641,7 @@ describe("admin API — reviewAuthorAllowlist field", () => {
3642
3641
  reviewAuthorAllowlist: input.reviewAuthorAllowlist ?? [],
3643
3642
  patchAuthorAllowlist: [],
3644
3643
  restrictSlackToMembers: false,
3645
- typeName: "coding",
3644
+ specialty: "coding",
3646
3645
  createdAt: new Date("2024-01-01"),
3647
3646
  updatedAt: new Date("2024-01-01"),
3648
3647
  missingRequiredEnv: [],
@@ -3712,7 +3711,7 @@ describe("admin API — patchAuthorAllowlist field", () => {
3712
3711
  reviewAuthorAllowlist: [],
3713
3712
  patchAuthorAllowlist: [],
3714
3713
  restrictSlackToMembers: false,
3715
- typeName: "coding",
3714
+ specialty: "coding",
3716
3715
  createdAt: new Date("2024-01-01"),
3717
3716
  updatedAt: new Date("2024-01-01"),
3718
3717
  missingRequiredEnv: [],
@@ -3734,7 +3733,7 @@ describe("admin API — patchAuthorAllowlist field", () => {
3734
3733
  reviewAuthorAllowlist: [],
3735
3734
  patchAuthorAllowlist: input.patchAuthorAllowlist ?? [],
3736
3735
  restrictSlackToMembers: false,
3737
- typeName: "coding",
3736
+ specialty: "coding",
3738
3737
  createdAt: new Date("2024-01-01"),
3739
3738
  updatedAt: new Date("2024-01-01"),
3740
3739
  missingRequiredEnv: [],
@@ -3801,7 +3800,7 @@ describe("admin API — trialExpiresAt field", () => {
3801
3800
  reviewAuthorAllowlist: [],
3802
3801
  patchAuthorAllowlist: [],
3803
3802
  restrictSlackToMembers: false,
3804
- typeName: "coding",
3803
+ specialty: "coding",
3805
3804
  createdAt: new Date("2024-01-01"),
3806
3805
  updatedAt: new Date("2024-01-01"),
3807
3806
  missingRequiredEnv: [],
@@ -3825,7 +3824,7 @@ describe("admin API — trialExpiresAt field", () => {
3825
3824
  reviewAuthorAllowlist: [],
3826
3825
  patchAuthorAllowlist: [],
3827
3826
  restrictSlackToMembers: false,
3828
- typeName: "coding",
3827
+ specialty: "coding",
3829
3828
  createdAt: new Date("2024-01-01"),
3830
3829
  updatedAt: new Date("2024-01-01"),
3831
3830
  missingRequiredEnv: [],
@@ -3875,7 +3874,7 @@ describe("admin API — trialExpiresAt field", () => {
3875
3874
  reviewAuthorAllowlist: [],
3876
3875
  patchAuthorAllowlist: [],
3877
3876
  restrictSlackToMembers: false,
3878
- typeName: "coding",
3877
+ specialty: "coding",
3879
3878
  createdAt: new Date("2024-01-01"),
3880
3879
  updatedAt: new Date("2024-01-01"),
3881
3880
  missingRequiredEnv: [],
@@ -3899,7 +3898,7 @@ describe("admin API — trialExpiresAt field", () => {
3899
3898
  reviewAuthorAllowlist: [],
3900
3899
  patchAuthorAllowlist: [],
3901
3900
  restrictSlackToMembers: false,
3902
- typeName: "coding",
3901
+ specialty: "coding",
3903
3902
  createdAt: new Date("2024-01-01"),
3904
3903
  updatedAt: new Date("2024-01-01"),
3905
3904
  missingRequiredEnv: [],
@@ -3953,7 +3952,7 @@ describe("admin API — trialExpiresAt field", () => {
3953
3952
  reviewAuthorAllowlist: [],
3954
3953
  patchAuthorAllowlist: [],
3955
3954
  restrictSlackToMembers: false,
3956
- typeName: "coding",
3955
+ specialty: "coding",
3957
3956
  createdAt: new Date("2024-01-01"),
3958
3957
  updatedAt: new Date("2024-01-01"),
3959
3958
  missingRequiredEnv: [],
@@ -3998,7 +3997,7 @@ describe("admin API — trialExpiresAt field", () => {
3998
3997
  reviewAuthorAllowlist: [],
3999
3998
  patchAuthorAllowlist: [],
4000
3999
  restrictSlackToMembers: false,
4001
- typeName: "coding",
4000
+ specialty: "coding",
4002
4001
  createdAt: new Date("2024-01-01"),
4003
4002
  updatedAt: new Date("2024-01-01"),
4004
4003
  missingRequiredEnv: [],
@@ -5175,7 +5174,7 @@ describe("non-admin session cookie scoping", () => {
5175
5174
  (
5176
5175
  await req(app, memberCookie, "/agents", "POST", {
5177
5176
  name: "x",
5178
- typeName: "coding",
5177
+ specialty: "coding",
5179
5178
  })
5180
5179
  ).status,
5181
5180
  ).toBe(403);
@@ -5261,32 +5260,32 @@ describe("admin API — account users create and delete agents (SSP-4.2)", () =>
5261
5260
  },
5262
5261
  });
5263
5262
 
5264
- it("account user creates an agent stamped with their own accountId and the self-serve typeName", async () => {
5263
+ it("account user creates an agent stamped with their own accountId and the self-serve specialty", async () => {
5265
5264
  const { deps, created } = makeAccountDeps("acct-a");
5266
5265
  const res = await post(
5267
5266
  createAdminApp(deps),
5268
- { name: "Mine", typeName: "coding" },
5267
+ { name: "Mine", specialty: "coding" },
5269
5268
  await accountCookie(),
5270
5269
  );
5271
5270
  expect(res.status).toBe(200);
5272
5271
  expect(created).toHaveLength(1);
5273
5272
  expect(created[0]).toMatchObject({
5274
5273
  accountId: "acct-a",
5275
- typeName: getSelfServeSpecialty(),
5274
+ specialty: getSelfServeSpecialty(),
5276
5275
  });
5277
5276
  });
5278
5277
 
5279
- it("ignores a client-supplied accountId and typeName", async () => {
5278
+ it("ignores a client-supplied accountId and specialty", async () => {
5280
5279
  const { deps, created } = makeAccountDeps("acct-a");
5281
5280
  const res = await post(
5282
5281
  createAdminApp(deps),
5283
- { name: "Sneaky", typeName: "other-type", accountId: "acct-b" },
5282
+ { name: "Sneaky", specialty: "other-type", accountId: "acct-b" },
5284
5283
  await accountCookie(),
5285
5284
  );
5286
5285
  expect(res.status).toBe(200);
5287
5286
  expect(created[0]).toMatchObject({
5288
5287
  accountId: "acct-a",
5289
- typeName: getSelfServeSpecialty(),
5288
+ specialty: getSelfServeSpecialty(),
5290
5289
  });
5291
5290
  });
5292
5291
 
@@ -5294,7 +5293,7 @@ describe("admin API — account users create and delete agents (SSP-4.2)", () =>
5294
5293
  const { deps, created } = makeAccountDeps(null);
5295
5294
  const res = await post(
5296
5295
  createAdminApp(deps),
5297
- { name: "Nope", typeName: "coding" },
5296
+ { name: "Nope", specialty: "coding" },
5298
5297
  await accountCookie(),
5299
5298
  );
5300
5299
  expect(res.status).toBe(403);
@@ -5305,7 +5304,7 @@ describe("admin API — account users create and delete agents (SSP-4.2)", () =>
5305
5304
  const { deps, created } = makeAccountDeps("acct-a");
5306
5305
  const res = await post(
5307
5306
  createAdminApp(deps),
5308
- { name: "Admin Made", typeName: "coding", accountId: "acct-b" },
5307
+ { name: "Admin Made", specialty: "coding", accountId: "acct-b" },
5309
5308
  await makeSessionCookie(),
5310
5309
  );
5311
5310
  expect(res.status).toBe(200);
@@ -5327,7 +5326,7 @@ describe("admin API — account users create and delete agents (SSP-4.2)", () =>
5327
5326
  });
5328
5327
  const res = await post(
5329
5328
  app,
5330
- { name: "Q", typeName: "coding" },
5329
+ { name: "Q", specialty: "coding" },
5331
5330
  await accountCookie(),
5332
5331
  );
5333
5332
  expect(res.status).toBe(403);
@@ -5863,7 +5862,7 @@ describe("admin API — Anthropic credential guards (WIF-2.1)", () => {
5863
5862
  it("rejects claudeCodeOauthToken for an in-cluster agent under federation (400)", async () => {
5864
5863
  const { provisioner, res } = create(true, {
5865
5864
  name: "Fed Agent",
5866
- typeName: "coding",
5865
+ specialty: "coding",
5867
5866
  runtime: "in-cluster",
5868
5867
  claudeCodeOauthToken: "sk-ant-oat-secret",
5869
5868
  });
@@ -5878,7 +5877,7 @@ describe("admin API — Anthropic credential guards (WIF-2.1)", () => {
5878
5877
  it("rejects anthropicApiKey for an in-cluster agent under federation (400)", async () => {
5879
5878
  const { res } = create(true, {
5880
5879
  name: "Fed Agent",
5881
- typeName: "coding",
5880
+ specialty: "coding",
5882
5881
  runtime: "in-cluster",
5883
5882
  anthropicApiKey: "sk-ant-api-secret",
5884
5883
  });
@@ -5888,7 +5887,7 @@ describe("admin API — Anthropic credential guards (WIF-2.1)", () => {
5888
5887
  it("allows credentials for a self-hosted agent under federation", async () => {
5889
5888
  const { res } = create(true, {
5890
5889
  name: "Local Agent",
5891
- typeName: "coding",
5890
+ specialty: "coding",
5892
5891
  claudeCodeOauthToken: "tok",
5893
5892
  });
5894
5893
  expect((await res).status).toBe(200);
@@ -5897,7 +5896,7 @@ describe("admin API — Anthropic credential guards (WIF-2.1)", () => {
5897
5896
  it("allows credentials when federation is disabled", async () => {
5898
5897
  const { res } = create(undefined, {
5899
5898
  name: "Plain Agent",
5900
- typeName: "coding",
5899
+ specialty: "coding",
5901
5900
  runtime: "in-cluster",
5902
5901
  claudeCodeOauthToken: "tok",
5903
5902
  });
@@ -5923,7 +5922,7 @@ describe("admin API — POST/DELETE /agents/:id/repos", () => {
5923
5922
  reviewAuthorAllowlist: [],
5924
5923
  patchAuthorAllowlist: [],
5925
5924
  restrictSlackToMembers: false,
5926
- typeName: "coding",
5925
+ specialty: "coding",
5927
5926
  createdAt: new Date("2024-01-01"),
5928
5927
  updatedAt: new Date("2024-01-01"),
5929
5928
  missingRequiredEnv: [],