3701be76fa
## 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>