Files
paperclip/server
Jannes Stubbemann 3701be76fa fix: read-only agent config/skill endpoints should not require agents:create (#3725)
## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies
> - Access to agents, skills, and configurations is governed by a
per-company permission system
> - `agents:create` is a mutation-tier permission that controls who can
create or modify agents
> - `assertCanReadConfigurations` delegates to
`assertCanCreateAgentsForCompany`, effectively requiring `agents:create`
just to *read* agent configs, skills, and config revisions
> - That's a permission regression: any company member without
`agents:create` hits 403 on the Skills tab, agent config pages, and
revision history — but those responses are already secret-redacted
> - This pull request loosens the read gate to company membership only,
while keeping every mutation-adjacent gate at `agents:create`

## Linked Issues or Issue Description

No existing issue covers this directly — problem described in-PR
following the bug-report template:

**What happened**

`assertCanReadConfigurations` delegates to
`assertCanCreateAgentsForCompany`, effectively requiring the
mutation-tier `agents:create` permission just to *read* agent configs,
skills, and config revisions. Any company member without `agents:create`
hits 403 on the Skills tab, agent config pages, and revision history —
even though those responses are already secret-redacted
(`redactAgentConfiguration`, `redactConfigRevision`).

**Expected behavior**

Read-only configuration/skill/revision endpoints are readable by any
company member; only mutation-adjacent endpoints require
`agents:create`.

**Steps to reproduce**

As a company member without `agents:create`, open the Skills tab or an
agent config page (or `GET` the config/skill/revision endpoints) — the
request fails with 403.

## What Changed

- `server/src/routes/agents.ts`:
- `assertCanReadConfigurations` now requires company membership only
(plus the existing agent-key cross-company check). Previously it
required `agents:create`.
- `actorCanReadConfigurationsForCompany` (the boolean twin, used by `GET
/agents/:id` to decide whether to return a restricted detail) now uses
the standard try/catch-around-`assertCompanyAccess` pattern.
- `POST /companies/:companyId/adapters/:type/test-environment` is not a
pure read (it exercises adapter secrets) and now calls
`assertCanCreateAgentsForCompany` directly instead of going through
`assertCanReadConfigurations`. Behavior for this endpoint is unchanged.

## Verification

- Existing tests pass.
- Manual: log in as a company member without an `agents:create` grant.
Visit the Skills tab on an agent and the agent configuration panel —
both load. Try to edit the agent — blocked, as before.
- Manual: POST to
`/companies/:companyId/adapters/:type/test-environment` as the same user
— still 403.

## Risks

Low. The only behavior change is on read endpoints whose responses were
already redacted (\`redactAgentConfiguration\`,
\`redactConfigRevision\`). No secret escapes anywhere.

## Model Used

Claude Opus 4.6 (1M context), extended thinking mode.

## Checklist

- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] Thinking path traces from project context to this change
- [x] Model used specified
- [x] Tests run locally and pass
- [x] CI green
- [x] Greptile review addressed

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-12 10:36:49 -07:00
..