Add first-class security agent role to taxonomy (#4532)

## Thinking Path

> - Paperclip is the control plane for AI-agent companies, so agent
metadata is part of the platform's governance and audit surface.
> - The shared agent taxonomy in `@paperclipai/shared` is the source of
truth for allowed agent roles and their UI labels.
> - The current taxonomy lacks a `security` role, which causes Security
Engineer hires to collapse into `engineer`.
> - That breaks separation-of-duties evidence in telemetry and weakens
role-level audit fidelity even though it does not directly change
permissions.
> - This pull request adds `security` as a first-class shared role and
covers the prior rejection path with a regression test.
> - The benefit is that Security Engineer agents can now be persisted
and rendered under the correct role without schema or permission churn.

## What Changed

- Added `security` to `AGENT_ROLES` in
`packages/shared/src/constants.ts`.
- Added the `Security` display label to `AGENT_ROLE_LABELS` so existing
UI consumers render the new role automatically.
- Added a shared validator regression test proving `createAgentSchema`
accepts `role: "security"` and that the label stays stable.

## Verification

- `pnpm --filter @paperclipai/shared typecheck`
- `pnpm --filter @paperclipai/shared exec vitest run
src/adapter-types.test.ts`

## Risks

- Low risk. This is a shared enum expansion with no database migration
and no permission-model change.
- Residual risk: this PR does not backfill existing agents already
persisted as `engineer`; it only fixes new validations and labels going
forward.

> I checked `ROADMAP.md`/`doc` for overlap and did not find an existing
planned item covering this taxonomy fix.

## Model Used

- OpenAI GPT-5.4 via the Codex local adapter, with tool use and local
code execution enabled. The runtime did not surface a separate
context-window identifier in agent metadata.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [ ] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
This commit is contained in:
Dotta 2026-04-26 07:52:05 -05:00 committed by GitHub
parent df425fde96
commit c036bbfa98
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 15 additions and 1 deletions

View file

@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest"; import { describe, expect, it } from "vitest";
import { acceptInviteSchema, createAgentSchema, updateAgentSchema } from "./index.js"; import { AGENT_ROLE_LABELS, acceptInviteSchema, createAgentSchema, updateAgentSchema } from "./index.js";
describe("dynamic adapter type validation schemas", () => { describe("dynamic adapter type validation schemas", () => {
it("accepts external adapter types in create/update agent schemas", () => { it("accepts external adapter types in create/update agent schemas", () => {
@ -35,4 +35,16 @@ describe("dynamic adapter type validation schemas", () => {
}).adapterType, }).adapterType,
).toBe("external_adapter"); ).toBe("external_adapter");
}); });
it("accepts the security agent role and exposes its UI label", () => {
expect(
createAgentSchema.parse({
name: "Security Engineer",
role: "security",
adapterType: "codex_local",
}).role,
).toBe("security");
expect(AGENT_ROLE_LABELS.security).toBe("Security");
});
}); });

View file

@ -42,6 +42,7 @@ export const AGENT_ROLES = [
"cto", "cto",
"cmo", "cmo",
"cfo", "cfo",
"security",
"engineer", "engineer",
"designer", "designer",
"pm", "pm",
@ -57,6 +58,7 @@ export const AGENT_ROLE_LABELS: Record<AgentRole, string> = {
cto: "CTO", cto: "CTO",
cmo: "CMO", cmo: "CMO",
cfo: "CFO", cfo: "CFO",
security: "Security",
engineer: "Engineer", engineer: "Engineer",
designer: "Designer", designer: "Designer",
pm: "PM", pm: "PM",