Files
PaperClipAI/doc/LOW-TRUST-PRESETS.md
T
DottaandPaperclip 0829d94af2 fix(auth): derive low-trust human direction from existing execution records (#14775)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Low-trust review contains work that may include hostile input.
> - Its default intake boundary currently blocks direct human chat and
tasks outside that boundary.
> - Human direction should authorize the assigned work while preserving
containment.
> - Existing conversations and execution requests already identify
direct human instructions.
> - This pull request derives exact-task authority from those records
and the current assignee.
> - The agent can perform that work without gaining access to unrelated
tasks or privileged tools.

## Linked Issues or Issue Description

**What happened?**

A low-trust agent with a project boundary rejects its owner's direct
Agent Chat before provider execution. Human-assigned tasks outside that
project fail the same check.

**Expected behavior**

An authorized human can talk to the agent or assign it a task. The exact
task runs with its existing sandbox, credential, and tool restrictions.

**Steps to reproduce**

1. Enable Agent Chat and isolated workspaces. Configure a sandbox agent
with low-trust review scoped to an intake project.
2. Send the agent a direct board chat message, or assign it a
projectless task.
3. Observe `low_trust_boundary_mismatch` before execution.

Related: #14766 adds private task directories for repo-free low-trust
execution. It is now merged into master and included in the branch base,
so CI and staging verify the combined behavior.

## What Changed

- Derive owner-chat access from existing conversation identity.
- Derive exact-task access from the existing human requester and
server-owned request origin, including coalesced requests. Plugin and
external sender attribution do not authorize work.
- Follow existing `retryOfRunId` database links for automatic
continuations, checking company, agent, and task throughout; cancelled
ancestors cannot grant authority.
- Require a live run and current assignment. Preserve sandbox,
credential, privileged-tool, responsible-user, and quarantined-output
checks.
- Retain board backlog assignments in existing request records without
starting execution. Reassignment cancels old human requests in the
common service transaction, including plugin writes; late settlement
cannot revive them.
- Add real database and HTTP coverage for request provenance, retry
ancestry, cancelled runs, concurrent reassignment, spoofing, and
containment. Document the rule.
- Preserve legacy board assignment requests through their existing
source, reason, and human requester.
- Use the existing wrapped-error helper for concurrent chat-question
idempotency; a deterministic race test reproduces the CI failure before
the fix and passes after it.
- No new schema, migrations, or user-identity fields. Existing requester
columns hold attribution.

## Verification

- Passed the focused database, policy-retention, HTTP, and reassignment
tests locally. The HTTP test creates a task through the real board route
and checks the resulting persisted wakeup before exercising agent reads,
comments, mutations, and review handoff.
- Database tests hold a reassignment transaction open to verify coherent
authorization before and after commit, with a two-connection pool. They
cover retries, coalesced requests, cancelled ancestry, invalid
cross-company/agent/task links, cycles, and forged attribution.
- Full local `pnpm -r typecheck` and `pnpm build` passed on the final
commit (`d107c26df`). [Latest-head
CI](https://github.com/paperclipai/paperclip/actions/runs/36815589542)
passed: 54 successful checks, two expected skips, including all eight
browser-test shards. Greptile is 5/5 on this exact commit with no
unresolved threads. Local tests were targeted; the full test suite ran
through CI’s test matrix.
- The revised HTTP suite passed all 13 tests; database authorization
tests passed all 11, including legacy compatibility and late watchdog
settlement; the backlog route contract passed all 3 tests. Another 102
tests covering durable chat admission, wake queues, and Cursor execution
passed.
- All 90 interaction-service tests passed with both create calls
deliberately held until their optimistic reads complete, forcing
duplicate-key recovery. That forced race failed before switching to the
shared wrapped-error helper.
- Previous staging proof covered owner chat and projectless task
persistence. The simplified revision has not been redeployed; that
earlier proof is not claimed for the new implementation.

## Risks

- This is an authorization change: only the live run's exact task
qualifies, and normal responsible-user restrictions still apply.
- Existing request and retry records are authoritative. Merely naming a
responsible/originating user or an external connector sender does not
qualify.
- Reassignment invalidates existing human request records
transactionally. A cancelled run or request cannot regain authority when
the task is assigned back.
- Ordinary task exceptions require server-owned origin or the legacy
board assignment source/reason/actor combination. Existing owner chats
use conversation identity.

## Model Used

OpenAI GPT-6 in Codex, with reasoning, repository tools, code execution,
and browser testing. The runtime does not expose a more specific model
ID or context-window size.

## 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 searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-01 09:45:18 -05:00

5.7 KiB

Low-Trust Presets

Paperclip ships core trust preset names so containment decisions are enforced in Community Edition even when EE policy editing is unavailable.

Presets

  • standard: the default V1 company-visible collaboration model. This preserves existing behavior for normal agents.
  • low_trust_review: an opt-in containment preset for automated work that may consume hostile or prompt-injected input, such as untrusted pull requests, external tickets, dependency diffs, or generated review output.

Boundary Model

low_trust_review is resolved from existing JSON policy fields:

  • agent permissions: permissions.trustPreset and permissions.authorizationPolicy.trustBoundary
  • project policy: executionWorkspacePolicy.authorizationPolicy.trustBoundary
  • issue/run policy: executionPolicy.authorizationPolicy.trustBoundary

The resolver intersects those sources. Narrower wins. A low-trust preset must resolve to a concrete company-local project, root issue, or issue-id scope. If a policy source names another company, uses an unsupported preset, or lacks that scope for risky access, Paperclip fails closed.

Containment, Not Privacy

This is containment for hostile automated work. It is not a general project, issue, or human privacy system.

V1 standard work remains company-visible by default: board users and in-company actors can inspect company work objects unless a separate access-control feature changes that behavior. Low-trust containment instead limits what the low-trust agent can read or mutate through the Paperclip API and prevents raw untrusted output from being automatically promoted into higher-trust agent context.

Low-trust agents cannot read or mutate agent configuration, instruction bundles, or company skill configuration through direct grants. Configuration changes from low-trust work must go through higher-trust review and promotion paths instead.

Human-directed work

An authenticated board user can talk to a low-trust agent in their own Agent Chat or assign it a task outside its default intake boundary. Existing conversation identity authorizes owner chat. Ordinary tasks use the human requester already recorded on the run's wakeup requests, including coalesced requests. Each request retains its server-owned origin; plugin-attributed users do not count as board instructions. Legacy board assignment requests remain valid through their existing assignment source, reason, and human requester, without trusting old plugin human attribution. A board backlog assignment is retained as a completed assignment request with no run, so it authorizes the later system launch without starting work prematurely. No separate permission table or client-supplied human identity is needed. Responsible-user attribution, external connector sender attribution, and agent claims do not qualify.

At dispatch and API authorization, Paperclip checks the live run and current assignment in one database snapshot. The exception permits reading, commenting on, and updating only that run's exact task. It does not extend to another task, a child, a whole project, configuration, instructions, secrets, or runtime management. Normal responsible-user checks still apply. The exception is never stored in the inherited trust boundary.

Automatic retries and continuations follow the existing retryOfRunId database links, checking the same company, agent, and task at every step. Cancelled runs cannot authorize a retry. The common assignment transaction cancels prior human requests, including plugin and service reassignments. Assigning the task back cannot revive those requests, and late run settlement cannot undo cancellation. Sandbox and isolated workspace requirements still apply, as do malformed-policy and company-boundary checks.

Child→Parent Reporting Under Containment

The direct-parent report comment (doc/execution-semantics.md §6, "Child→Parent Reporting") is off by default for low_trust_review: a contained run reads untrusted input, so a free-prose comment into the higher-trust parent thread is a prompt-injection promotion path. Contained reviewers report by completing their own review issue (done — the verdict is the deliverable; the issue_blockers_resolved wake carries it upward) and by the platform's system-attributed stop-only relay when they enter blocked or cancelled. Never instruct a contained delegate to comment on its parent issue.

Runtime Containment

Managed low_trust_review runs fail closed unless Paperclip can enforce the runtime boundary:

  • the selected execution environment must use the sandbox driver
  • the effective execution workspace mode must be isolated_workspace
  • the issue being run must be inside the resolved low-trust boundary or be the exact human-directed task described above
  • secret references must use binding ids explicitly allowed by the boundary
  • inline sensitive environment values such as API keys and tokens are rejected
  • workspace runtime-service mutations are denied unless the boundary explicitly grants the runtime.manage tool class

When the task's project has no configured workspace and no layer specifies a workspace strategy, sandbox execution uses a private directory for that company and task. The directory persists across turns and reassignment and never imports the shared project directory or agent home. No Git repository is required for this case. Configured workspaces and explicit Git strategies keep their existing validation; a missing or broken checkout does not fall back to an empty directory.

The Docker workflow in doc/UNTRUSTED-PR-REVIEW.md remains useful for manual local review, but Paperclip-managed low-trust execution requires a sandboxed environment instead of a host-local adapter process.