Commit Graph
23 Commits
Author SHA1 Message Date
DottaandPaperclip c3a9a8e92a perf(server): scope run identity reads to operation needs (#17931)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Tool and connection operations capture the current accepted
requester.
> - Capture locks the task and run, then reconciles pending steering.
> - Most callers use identity or task fields from the returned run.
> - The default query also transfers saved prompts, runner
configuration, results, and logs.
> - This pull request gives each production caller an explicit read
scope.
> - Narrow scopes keep their authority checks and return only selected
columns.
> - The Muse project path still reads its complete saved execution
input.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Operation-time run identity capture for native tools, gateway sessions,
project and workspace access, Slack, voice, connection management, and
connection token admission.

**Current behavior**

These callers use the default full run read. Large saved execution
documents cross the database connection even when the caller only needs
the current accepted requester or task binding.

**Proposed behavior**

Use typed identity, task, broker, and project-execution scopes. Keep
task-before-run locks, company and agent predicates, active status
validation, and pending-steering reconciliation. Return the complete
saved native input only where project admission uses it.

**Reason and benefit**

A synthetic PostgreSQL 17.11 fixture matches a wide run with a 142 KB
context and a 77 KB runner profile. Its locked run DataRow falls from
225,101 bytes to 190–605 bytes for authority reads. The project scope
returns 66,004 bytes because it must retain a complete 64 KB execution
input. These are local DataRow measurements, not a forecast of
production billing or latency.

**Breaking changes**

None to public APIs, saved data, or authority policy. Internal narrow
return types omit columns that were not selected. The default full
compatibility read and the existing GitHub-credential and authentication
scopes keep their current contracts.

**Additional context**

The public issue and PR duplicate searches found no matching open
change. This is one independent query optimization. It does not require
other performance PRs.

## What Changed

- Add typed scopes for accepted identity metadata, task authorization,
token attribution, and saved project execution input.
- Assign explicit scopes at all production `captureRunIdentity` call
sites.
- Keep the full native execution input for Muse project admission while
omitting unrelated profile, context, result, and log data.
- Narrow the broker's initial read and the existing Slack and
connection-management historical reads to the same required fields.
- Extend steering and acknowledgement regressions to all new scopes. Add
real PostgreSQL projection, malformed JSON, tenant and agent,
session-generation, and saved-input coverage.
- Add a service-generated SQL benchmark with exact raw DataRow
accounting, retained-field equality, plans, and alternating transaction
timings.
- Document the scope contracts and reproducible benchmark.

## Verification

- Baseline: `623f1dc289a14a699ebbe3f09b94179d38fc2ae2`.
- `vitest run server/src/__tests__/run-identity-projections.test.ts
server/src/__tests__/run-identity.test.ts`: 54 tests passed on an owned
disposable PostgreSQL 17.11 database.
- The tests retain task-before-run and audit foreign-key lock behavior.
Every scope rejects uncertain steering, accepts its durable
acknowledgement, and preserves requester replay ordering.
- A full-row mutation makes the narrow identity regression fail. The
restored treatment passes.
- `pnpm --filter @paperclipai/server exec tsx
../scripts/benchmark-run-identity-projections.ts
--baseline-ref=623f1dc289a14a699ebbe3f09b94179d38fc2ae2` captures the
real locked SQL for both versions.
- Every retained column and selected JSON field matches the baseline.
Identity contexts match. The complete stored run remains unchanged.
Capture keeps the same five queries.

| Scope | Before DataRow bytes | After DataRow bytes | Reduction |
| --- | ---: | ---: | ---: |
| Identity | 225,101 | 190 | 99.92% |
| Task authorization | 225,101 | 410 | 99.82% |
| Token broker | 225,101 | 605 | 99.73% |
| Project execution input | 225,101 | 66,004 | 70.68% |

- DataRow bytes include row framing and raw text-format column values.
They exclude response metadata, TLS, and TCP.
- Two warmups and seven alternating samples measure the complete capture
transaction. Several timing ranges overlap. The primary claim is byte
reduction; production latency is not verified.
- Initial fixture runs exposed an empty external schema and an
incomplete synthetic conversation binding. The test setup now applies
migrations and supplies the required user/state fields. The final 54
tests passed.
- `pnpm -r typecheck` and `pnpm build` passed locally.
- Four existing skill-setup tests passed. Four assembled
connection-management/native-tool consumer cases passed with real
JWT/API-key authentication. These include per-request identity freshness
and task-scoped activity authority.
- A CI-only stale mock assertion expected two capture arguments; it now
verifies the explicit identity scope. A repository-wide capture mock
audit found no other stale argument assertions.
- Review follow-up: the projection suite uses the existing
embedded-support guard while always enabling an explicitly supplied
external database. The audit-lock regression merges URL query parameters
and retains existing PostgreSQL options.
- `vitest run server/src/__tests__/run-identity-projections.test.ts
server/src/__tests__/run-identity.test.ts
server/src/__tests__/company-skills-routes.test.ts
server/src/__tests__/project-skill-setup-identity.test.ts`: 123 tests
passed. The external PostgreSQL URL included both `application_name` and
`options`; lock tests verified `lock_timeout=1s` and retained
`statement_timeout=5s`.
- Full local tests are not run because the host's embedded PostgreSQL
setup is unavailable. Greptile reviewed
`06e1dd53a3fb24df74d5fbfb2ad397f291f1e30f` at 5/5 with zero unresolved
threads. The full final-head CI matrix passes. All 58 checks are
terminal: 55 success, one neutral, and two optional Storybook skips.
- No migration, lockfile, workflow, new polling, or cache change.

## Risks

A narrow read must retain each caller's actual fields. The caller audit
includes Slack's wake-request fallback, conversation generation, legacy
broker attribution, and the Muse parser's complete native input. JSON
selection retains value types, including malformed legacy values. The
saved-input scope preserves missing-key behavior. The default full read
still returns the complete stored row for compatibility. Locks and live
authority checks are unchanged.

## Model Used

OpenAI GPT-6, accessed through Codex. The exact runtime model ID and
context-window size were not exposed in this session. Used repository
inspection, code execution, and PostgreSQL validation.

## 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-27 16:31:21 -05:00
DottaandPaperclip 13709b4c7a feat(connections): let agents configure connections within delegated authority (#17737)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Connections provide governed tools, chat channels, model accounts,
and gateways.
> - Several management routes require a human board actor even when an
agent has the required grant.
> - Default agents must configure these resources within the responsible
user's authority.
> - This pull request adds a shared authorization path to the existing
REST and native API surface.
> - Human authentication, execution approvals, and local host boundaries
remain enforced.
> - The benefit is that a standard agent can complete authorized setup
with a bounded human handoff.

## Linked Issues or Issue Description

**Subsystem affected**

Server authorization, connection services, shared contracts, native API
discovery, database schema.

**Problem or motivation**

Connection administration is available in the web app but often
unavailable to agents. Agent grants, responsible-user authority,
credential ownership, and actor attribution need separate checks.
Opening gateway-token creation also requires preserving the issuing
agent's delegated authority during token use.

**Proposed solution**

Use the existing authorization evaluator for every connection family.
Enforce current responsible-user authority, effective trust, grant
scope, resource visibility, and target-agent access. Keep existing agent
grants unchanged. Expose authorized configuration through default
`search_api` and `call_api`. Save human authentication steps and let
agents continue after completion.

**Roadmap alignment**

This change completes the API access path for the existing Connected
Apps, Personal & Shared AI Accounts, and governed MCP Gateway
capabilities in `ROADMAP.md`. It follows the maintainer's requested
design. Related work: #11899 enforces connection execution access and
creator/manager rules; this PR extends agent management across
connection families. It does not replace that execution-policy work.

## What Changed

- Add shared connection management context and mandatory
responsible-user, trust, scope, and target checks.
- Allow authorized agents to configure tool, chat/email, GitHub/Slack,
AI, profile, and gateway resources through existing routes.
- Preserve human credential ownership and record the actual agent,
responsible user, and run or key in audit data.
- Preserve saved browser authentication handoffs and callback session
checks.
- Bind agent-issued durable gateway tokens to their responsible user and
recheck delegated authority at use.
- Add explicit REST transport and management capability metadata,
built-in guidance, and sensitive-response handling.
- Intersect caller and endpoint-agent Slack test/invitation policies,
including independent and shared rates. Require the addressed human’s
current endpoint identity link before completing identity handoffs.
- Add production-authenticated integration scenarios. Companion #17739
contains the saved setup UI (including the required human
import/rotation step), product and permission documentation,
catalog/Vercel credential and callback ownership, and operation maps to
keep each review below 100 files. Both PRs must ship together; merge
this implementation first, then its companion.

## Verification

- Current implementation head:
`2ecd6451d0d0c8d82121a4e3fa4ce94c5befbbd6`, including master
`ea727dc3c2`, 99 files. The latest follow-up fixes the two valid
findings from the preceding f9 review. Exact-head Greptile has completed
at5/5 with no findings and Superagent passed. Full exact-head Linux CI
workflow40446606056 completed SUCCESS; only the queued external
Paperclip Review remains pending; earlier Linux passes do not qualify
this successor.
- Latest preserved-stack verification passed **2,165 tests** in fresh
PostgreSQL: **70 actual-auth scenarios**, 27 OpenAPI contracts, 2,022
native API tests and 46 saved GitHub wizard cases. **141 existing
gateway/policy acceptance tests** also passed. Workspace
typecheck/build, maps and token gates passed. The first workspace
typecheck was blocked by sandbox tsx IPC permissions; its authorized
rerun passed. This is focused local evidence; the full Linux CI matrix
is still required.
- Issuer/target gateway policy regressions were red before the fix. Both
decisions now intersect, including Block/Ask first/rates, same
credential identity and current token/user/agent authority after
approval. Invocations retain their token and actual requesting agent;
deleted tokens fail closed. Thirteen actual-auth cases cover revocation,
narrowed scope, approvals, shared rates and board compatibility.
Intermediate missing-token attribution, review-context and
implicit-session actor failures remain in the qualification record; all
final cases pass.
- Activity pagination now retains a bounded cursor across private-only
windows. The actual-JWT regression reaches three older readable events
after 27 private ones without exposing private details. A native
device-login regression was red for plaintext receipts; local check and
test-call results now use existing protected-response handling. The
passing actual-auth case proves encrypted persistence, exact replay,
redacted history and no response asset.

- Previous-head `5b55195593` Linux CI initially failed e2e shard 4/8 in
the existing connection-intent continuation test: periodic recovery
queued a repair at 01:21:47, the scripted journey completed the task at
01:21:48, and the extra queued run was cancelled at 01:21:49 because the
task was terminal. The assertion selected that latest cancelled run.
GitHub refused the first attempt while the workflow was nonterminal.
After completion, the single evidence-supported failed-job rerun was
accepted as **attempt 2** on the same head (workflow 40431202466). The
failed shard and final E2E aggregate passed on attempt 2, and the
complete Linux workflow for that head is successful. The original
failure remains part of qualification. No additional unchanged-code
rerun will be used for this failure.

- Companion CI also has an unchanged login-cleanup idleness timeout,
retained in its qualification record. That same 16-case suite passed in
this parent Linux run and a fresh local database. Both preceding
workflows passed after their single failed-job reruns as attempt 2; the
original failures remain recorded. No additional unchanged-code rerun
was used.

- Migration `0380_broken_aqueduct.sql` was regenerated through the
repository workflow after master took 0379 for project Git
authorization. It adds the responsible-user column with `IF NOT EXISTS`,
preserves upstream migrations, and satisfies snapshot retention and
migration safety checks.
- Upstream published Copilot v62 and v63 identities remain byte-for-byte
unchanged. The combined guidance is now v64, digest
`sha256:22e31f95ef972bcead98a4a707c9f33433558fd111e390e027a2bbb4346e112a`.
The normal shared TypeScript/Rust identity check and **61 Copilot
installation tests passed**. The old source-identity assertion first
failed against unchanged published v63; regenerating a new v64 preserves
the published release.
- Workspace `pnpm -r typecheck` and `pnpm build`, map validation, and UI
token gates passed on the final combined stack after the upstream merge.
Node 24.22.1 / pnpm 9.15.4 were used.
- **Earlier 82 API/OpenAPI tests passed** in fresh PostgreSQL 18: 55
assembled-server scenarios and 27 contracts. They use real persistent
agent keys, run JWTs, human sessions, production defaults, and
deterministic provider fixtures. No actor injection establishes access.
- The new email regression was red before per-account scope filtering.
The Arcade regression was red before human ownership and inventory-key
fixes; it also verifies actual-agent audit identity and a human-session
inventory read. The activity regression measured **200 authorization
checks before the fix and one afterward** for the same one-item page.
- **82 GitHub UI tests passed**, including all three new
failed-replacement regressions that were red before their fix. The UI
preserves an earlier copy only after confirming its committed
generation. Changed or unreadable results block copying and reconnecting
until reconciled. Human-only secret responses now include their
nonsecret committed generation.
- Private test status now rechecks the originating principal and linked
task, including mandatory agent/responsible-user privacy. Cross-agent
tests require the full caller tool access decision and the same
credential identity, regardless of auth label; caller and target
policies/approvals and rate limits apply before execution and after
human approval. A profile-only precondition was found to reject valid
allow-policy and scoped-grant access and has been removed. Both
permitted-access cases and a no-auth-label identity regression were red
before the correction; caller-specific Block still prevents provider
execution. The private-status regression was also red before its fix.
- The tool-activity regression measured 100 capability decisions and 102
run captures on a 100-event page before the fix. It now uses two task
decisions and at most two captures while retaining the same 50 visible
events, private-event filtering, and 403 after audit-grant revocation.
The regression was red before request-context reuse and task-decision
sharing; final server typecheck/build also pass.
- Generic chat configure/reconnect now hands agent-supplied verification
credentials to the addressed human before provider work or vault
changes. Actual key/JWT regressions were red for Slack signing-key
replacement and generic channel secret-reference rebinding. They now
prove unchanged refs and vaulted signing value, human setup, permitted
agent bot-token repair, and governed test messages. All 82 API/OpenAPI
cases pass in fresh PostgreSQL. Eight native receipt protections and
final server typecheck/build also pass.
- The preceding review found that old healthy state could retire a
credential-entry card before a human changed anything. The actual-JWT
regression was red. Saved field generations now change only with
protected values and commit with refs plus a verification fence; retries
retain the baseline. Old health, bot-token repair and unchanged entry
stay pending. New signing verification and current authority permit
continuation. A separate red race proved that user revocation during
provider authentication could return 403 after refs changed; authority
is now checked before persistence and inside the credential transaction.
The final 82 API/OpenAPI cases, four neighboring real-database
Slack/GitHub lifecycle cases, and final server typecheck/build pass.
- A preceding full run crossed a rate-window boundary. Database rows
prove one consumed slot at 23:35 and another at 23:36 for the same
policy/bucket. Only Date is frozen in the rate test cases; transport and
asynchronous timers remain real. Production rate behavior is unchanged,
and the final full run passes. An intermediate fixture failure that
overwrote hidden generation metadata with an API projection is retained
in the qualification record.
- Linux CI on an earlier head found two rate-admission assertions that
omitted the newly persisted bucket key. The failures were reproduced
locally; both assertions now verify the exact actor/tool bucket and all
49 policy-service tests pass. The companion qualification record retains
the initial and intermediate failures. Catalog creator attribution is
preserved in the companion to keep this implementation review at 99
files.
- The latest review reproduced three regressions before repair: complete
human replacements failed on unavailable old signing secrets, fresh
GitHub links incorrectly selected reconnect, and different
credential-entry requests shared an idempotency key. Each old protected
ref now has a narrow known-unavailable fallback; unexpected resolver
failures and company/scope violations still abort. Fresh imports keep
their credential form, configured endpoints keep reconnect, and
canonical field sets/completion modes distinguish handoffs while
matching retries retain their baseline. All 55 actual-auth scenarios and
27 separately run OpenAPI contracts pass, as do server typecheck/build.
Companion #17739 also passes all 41 wizard tests including actual
fresh-form submission, UI typecheck, maps and token gates. Earlier red
results and a mistyped OpenAPI filename are retained in qualification.
- The configured GitHub handoff regression was red in the
browser-component tests and actual-auth link/persistence tests. Saved
links now name requested fields and all/any completion mode; the
companion form submits those supplied fields through reconnect and
retains other saved credentials. Webhook/client-secret reconnect remains
human-only; first-setup secret restrictions remain. All 46 wizard tests
pass, including combined modes and legacy links. A duplicate review
referenced the older companion bf760912; the current form is already
fixed, linked in the reply, and its thread is resolved.
- Linux CI on bf760912 failed automatic Slack provisioning because vault
persistence cleared an already verified manifest-update challenge. The
same regression was reproduced locally. The provider-owned helper now
preserves proof only for the current signing fingerprint and callback
URL. Eight existing compatibility cases pass, including this case and
initial GitHub secret rejection. The first uncommitted GitHub-field
variant also failed that initial boundary and was narrowed to reconnect;
both failures remain in qualification.
- The upstream merge conflicted only in generated migration metadata.
Upstream 0379 is preserved, normal generation/pruning produced 0380, and
two repeated applications of the idempotent additive SQL passed. The
final combined stack passed **128 tests** (55 actual-auth, 27 OpenAPI
and 46 wizard cases) in fresh PostgreSQL. Eight Google UI cases also
pass; the two protocol cases could not initialize embedded PostgreSQL in
this fresh local attempt. Their earlier passing evidence remains
historical; fresh Linux CI must execute them. Vercel personal credential
attribution is preserved in companion #17739 with its other
ownership/consent follow-ups, keeping this PR at 99 files.
- The suite covers fresh defaults, restricted users/agents, scopes,
personal isolation, token revocation, human handoffs, callback replay,
execution approvals, authorized self-targeted policy changes,
self-approval denial, and current authority before commit. Reproduce API
checks with `pnpm exec vitest run
server/src/__tests__/connection-management.integration.test.ts
server/src/__tests__/openapi-routes.test.ts`, using a fresh database
through `PAPERCLIP_CONNECTION_MANAGEMENT_TEST_DATABASE_URL` or the
default embedded test database.
- Companion #17739 also records consent separately from token refresh so
saved Google choices survive refresh. Its eight service-picker and two
local-HTTP OAuth tests pass; both new UI cases were red before the fix.
Normal migration generation confirms no SQL change is needed for the
additive JSON metadata.
- The integration module shares one assembled server, authentication
factory, and provider lifecycle to preserve the
HTTP-to-vault-to-task-continuation proof. A reused external database
caused a Slack fixture identity conflict; the fresh final run passed.
Earlier fixture/transport and contract-update failures remain in the
companion qualification record.
- The broad local `pnpm test:run` attempt remains blocked by macOS
embedded PostgreSQL's host semaphore limit. It is not a clean pass. The
fresh Linux CI matrix must complete. Provider fixtures do not prove live
setup or an empirical LLM success rate.
- A current-head completed Paperclip assessment is not yet recorded. Its
earlier external recovery boundary has not been bypassed, and no
incomplete assessment is reported as passing. The user authorized both
merges when checks pass; merge this implementation first, then replay,
retarget, and requalify companion #17739 against the squash-merged
master.

- After the master refresh, local workspace typecheck/build, **97
actual-auth/OpenAPI cases** and **141 gateway/policy cases** pass. The
original fixed database port was occupied; Docker assigned a free
localhost port. The first neighbor setup command could not resolve root
`tsx`, leaving its schema uninitialized; the built database package
migrated the separate fixture and all unchanged cases passed. Both setup
failures are retained in qualification. Fresh Linux CI remains required;
no full local test-sweep pass is claimed.

- The f9 Greptile review scored **2/5** for two reproduced findings:
Slack test sends skipped the caller’s tool policy, and healthy App
credentials completed an unconfirmed identity handoff. Both are fixed in
this head and have resolved evidence threads
([Slack](https://github.com/paperclipai/paperclip/pull/17737#discussion_r4384927765),
[identity](https://github.com/paperclipai/paperclip/pull/17737#discussion_r4384927895)).
Actual key/JWT cases cover twelve Slack caller/target/recipient
combinations; the human-session GitHub OAuth callback alone remains
pending until explicit confirmation. All **99 API/OpenAPI tests** (72
actual-auth + 27 contracts), workspace typecheck and build pass. On the
combined companion, all four focused cases (including the twelve Slack
combinations), typecheck/build and maps also pass. The continuation
suite’s 50 embedded-PG cases were skipped because its database could not
start locally; fresh Linux CI must run them. Initial fixture
credential-collision and audit-projection assertion failures are
retained with the red reproductions in the companion qualification
record. No full local sweep or live consent is claimed.

## Risks

- The maintainer explicitly confirmed authorized policy administration,
including self-targeted changes that loosen controls. These writes
require management grants and the responsible user’s current authority.
Agents cannot approve their own governed action requests or edit their
own principal permission grants. The actual-auth regression exercises
both permitted administration and those denials.
- This is a broad authorization change. Incorrect scope or owner
resolution could deny permitted setup or expose another user's
resources. Integration cases cover both permitted and denied requests
with actual authentication.
- The additive nullable gateway-token column does not infer identities
for legacy clients or backfill agent grants. Legacy agent tokens without
a responsible user fail closed.
- Provider fixtures test supported setup and callback contracts. They do
not prove live provider availability.

## Model Used

- OpenAI Codex, GPT-6 family, with reasoning, repository tools, and code
execution. The runtime does not expose a more specific deployment 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 — focused suites above;
full local sweep remains blocked as documented
- [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
- [ ] All Paperclip CI gates are green — exact `2ecd6451d0` Linux CI
completed SUCCESS; external Paperclip Review is still queued
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups —
exact `2ecd6451d0` review completed; both f9 findings have resolved
evidence replies
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 08:20:24 -05:00
DottaandPaperclip 4d90634f74 feat(connections): add 1Password service-account connector (#17249)
## Thinking Path

> - Paperclip lets people manage AI agents and govern their access to
outside services.
> - Apps connections keep provider credentials in the instance vault and
mediate every action through grants, policies, and audit.
> - Agents currently have no Apps connection for reading or managing
1Password items with an operator-supplied service-account token.
> - 1Password supports this through its official SDK; its documentation
MCP server does not expose vault operations.
> - This pull request adds a one-field service-account connection and
registers eight reviewed SDK actions through the existing
native-provider catalog.
> - Operators can select vault permissions in 1Password and agent/action
access in Paperclip without installing a CLI or handing durable
credentials to agents.

## Linked Issues or Issue Description

Related: #16144 adds 1Password as Paperclip's secret-storage backend.
This PR adds the separate Apps/tool-access flow with a per-connection
credential; it does not change secret providers or use a server-wide
ambient token.

**Subsystem affected**
Apps catalog, native tool-provider registry, and shared connection
setup.

**Problem or motivation**
People need to paste their own `OP_SERVICE_ACCOUNT_TOKEN`, find official
service-account setup instructions, and authorize agents to use the
selected vaults through ordinary Paperclip governance.

**Proposed solution**
Add `1password/service-account`, with a password field labeled **Paste
your 1Password Service Account token** and a link to [1Password's
creation
instructions](https://www.1password.dev/service-accounts/get-started#create-a-service-account).
Use the pinned official `@1password/sdk` 0.5.0 for vault/item listing,
item and secret-reference reads, and item create/update/archive/delete.

**Alternatives considered**
A remote MCP card would not provide vault access. A local CLI or a
third-party MCP package adds installation and credential surfaces that
the official SDK avoids.

## What Changed

- Added the source and generated catalog definition, permission review,
official light/dark artwork, documentation, and capability-map
references.
- Added a provider-owned SDK bridge with strict schemas, account-domain
validation, contract hashes, fixed errors, bounded output, and
disposable workers with cancellation/deadlines.
- Registered the provider through master's native-provider catalog;
existing setup, health, discovery, gateway, policy, and audit owners
remain in place.
- Labeled the single password field **Paste your 1Password Service
Account token**. The shared formatter preserves explicit credential
prompts; ordinary key labels retain their existing presentation.
- Added credential-ownership, gateway read/write, policy/revocation,
worker, setup UI, and interactive Storybook coverage.

## Verification

- Final review follow-up: added two deterministic worker-entry tests for
nested exact-token redaction and oversized-output rejection. Removing
each guard caused exactly its regression test to fail. The focused
provider suite passed **15 tests**, and the official server typecheck
passed after rebuilding stale workspace SDK artifacts. Current head
`569cb7f9bd57db791fb13a6034ce69bf50878cb1` passed the full [CI
run](https://github.com/paperclipai/paperclip/actions/runs/40016166260),
including typecheck, build, unit/integration tests, and all eight
browser shards. The required `ci / verify` and `ci / e2e` gates passed.
[Greptile](https://github.com/paperclipai/paperclip/pull/17249#issuecomment-6353731805)
and [Paperclip
Review](https://github.com/paperclipai/paperclip/pull/17249#issuecomment-6372165895)
each rated this exact head **5/5**, with no open findings. Paperclip
Review completed with a neutral check because its scoped reviewer could
not inspect CI; the full CI result was verified separately. Other
neutral checks and intentionally skipped Storybook jobs contain no
actionable findings.
- CI recovery on the same commit: the first attempt lost six jobs. Five
logged simultaneous runner shutdowns at 18:49 UTC on 2026-10-23; the
sixth stopped logging before a test result and its root cause was not
established. No assertion failure appeared in the retrieved logs. All
six jobs and the aggregate gates passed one failed-job retry. [CI
run](https://github.com/paperclipai/paperclip/actions/runs/40005754936).
- Copy follow-up: the catalog, provider, and setup UI suites passed
**275 tests**. The governed gateway lifecycle passed **3 tests** (one
live-only test skipped), including create, update, archive, and delete.
UI token gates and map checks passed. The branch was rebased onto
`9c442cf48e` to resolve additive catalog conflicts while retaining the
Vercel and Supabase entries. The existing live write proof below remains
applicable; this follow-up changes presentation only.
- Five affected suites, including the existing Daytona consumer, passed
**290 tests** (one opt-in live test skipped in fixture mode). Full `pnpm
-r typecheck` and `pnpm build` passed. The local broad-suite attempt
could not complete because PostgreSQL semaphore exhaustion prevented a
competing integration suite from starting; the complete affected-file
retry passed after disposable-process cleanup. The prior commit
`f208a8aff6dc28859cc3f343497e18d85f124579` passed the complete CI
matrix. All CI build, typecheck, test, and browser gates also passed on
the earlier commit `9e2f3d3140368a08da43b004b2e8d3a0f4c0fa4d`. The
separate Paperclip Review reported a worker-result regression-test gap
on that head; the follow-up above addresses it. Its review thread is
resolved, and both fresh current-head reviews are clean as recorded
above.
- Token gates, module boundaries, brand validation, map checks, and
Storybook catalog checks passed.
- Direct SDK create/archive/delete and rejected-call coverage passed (13
provider tests); the Storybook Permissions/Test play completed
successfully in Chromium. Server and UI typechecks passed after those
fixes. Greptile passed prior commit
`9e2f3d3140368a08da43b004b2e8d3a0f4c0fa4d` at **5/5**. Both reviewers
also passed the worker-test follow-up at **5/5** as recorded above.
- Live 1Password proof on 2026-10-22: connect, eight-action discovery,
vault listing through an actual run-scoped gateway, refresh, reconnect
preserving identity, another read, removal, and denial through the
retained session passed. Credential absence was asserted in
responses/audit; an exact-token scan of inspected logs and changed files
passed.
- Real browser: Connectors → 1Password → token entry → personal access
limited to one disposable agent → completion → Permissions → Test
`onepassword_list_vaults` succeeded. The disposable connection was
removed afterward.
- Compiled-worker smoke initially exposed inherited Node launch flags.
Workers now use explicit empty `execArgv`; the compiled worker then
authenticated successfully and listed one vault.
- Live write proof on **2026-10-23**: the replacement Keychain token
passed all eight actions through the actual run-scoped gateway for both
personal and shared credentials. The test created, listed, read,
updated, resolved a secret from, archived, and deleted two synthetic
items. Both were absent from subsequent item lists. Refresh/reconnect,
identity preservation, removal, retained-session denial, and credential
absence passed. The live suite passed **3 tests** (one fixture-only test
skipped) in 116.65 seconds. The expanded fixture suite passed **3
tests** (one live-only test skipped); the 13 provider tests and server
typecheck passed. An exact-token scan passed over 64 source/log files.
- Failure history: the original token denied creation on 2026-10-22 and
created no item. The first 2026-10-23 attempt stopped before provider
calls because host PostgreSQL semaphore limits prevented test-database
startup. A temporary ten-connection test profile allowed the complete
retry to pass without changing shared services or host limits. A new
delete-result assertion also exposed an outdated fixture response
(`success` instead of `deleted`); the fixture was corrected and the
complete fixture suite passed.

Official contract sources: [service
accounts](https://www.1password.dev/service-accounts/get-started),
[SDKs](https://www.1password.dev/sdks), [item
management](https://www.1password.dev/sdks/manage-items), [official
JavaScript SDK](https://github.com/1Password/onepassword-sdk-js).

## Risks

- Authorized item/secret reads intentionally return secret values to the
agent and ordinary tool-result history. Select trusted agents and use
restricted service-account vaults; the connection token itself is
redacted.
- New connections retain existing Paperclip action defaults, including
Allowed writes/destructive actions for selected agents. 1Password still
enforces the token's permissions.
- Service-account access cannot be changed in place. Create a
replacement account and reconnect to change vault permissions; read-only
keys can connect but cannot write.
- SDK authentication happens per action in a disposable worker. Calls
have a 30-second maximum; cancellation stops local work, while a
mutation already accepted by 1Password can still finish. Writes are
never automatically retried.
- Additive dependency and catalog change; no database migration.
Disable/remove the connection to withdraw access, or remove the provider
from catalog visibility for rollback.

## Model Used

OpenAI Codex, based on GPT-6, with code editing, shell/browser tools,
and live provider verification. A more specific runtime model ID and
context-window limit were not exposed in this session.

## 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-23 13:27:33 -07:00
DottaandPaperclip 9c442cf48e feat(connections): deploy and configure Supabase and Vercel (#17217)
Add governed Supabase and Vercel deployment/configuration connectors with vaulted credentials, agent access policies, approvals, audit, and bounded provider operations.

Deliver reviewed REST actions to native agents and guard Vercel preview intent on empty projects. Preserve secret-safe request identity and durable retry behavior.

Verified by current-head CI, fresh Greptile 5/5 review, and real-agent deployment/configuration walkthroughs on disposable provider resources. Test resources and temporary provider tokens were removed after verification.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-23 11:37:29 -07:00
Devin Foley 059ae49cab feat(connections): add Unikraft Cloud connection (#17139)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Apps connections give agents governed access to external services
through vault credentials, grants, action policies, the tool gateway,
and audit.
> - Unikraft Cloud runs unikernel micro-VMs, services, and volumes
across regional metros, and it offers a sandbox plugin for commands and
files.
> - Unikraft is not in the catalog. It has no hosted MCP server, so the
generic "Connect your own MCP server" flow cannot reach it.
> - Daytona (#16483) added a native REST pattern for this case: a
catalog generated from the provider's published OpenAPI specifications
and executed through the gateway.
> - This pull request adds Unikraft on that pattern and moves the shared
native-provider code into one registry, so the shared connection code
does not name each provider.
> - The benefit is governed agent access to all published Unikraft
actions, with the token kept in the vault and sent only to published
Unikraft hosts.

## Linked Issues or Issue Description

Refs #16483

**Problem or motivation**

Teams that run workloads on Unikraft Cloud want their agents to list
instances, read logs, deploy and scale services, and run commands in
sandboxes. Unikraft is not in the Apps catalog. Unikraft has no hosted
MCP server, so operators cannot connect it through the remote MCP flow.

**Proposed solution**

Add a native Unikraft connection. Generate its actions from Unikraft's
official OpenAPI specifications for the platform API and the sandbox
plugin. Pin the specifications to a reviewed commit. The operator
connects an API token. The token stays in the vault and goes only to the
five published metro hosts. Every action takes an optional metro.
Actions without a metro use the connection's default metro, which the
operator can change under Advanced.

**Alternatives considered**

A catalog-only AppDefinition was not possible because no hosted MCP
endpoint exists. Wrapping the `unikraft` CLI was rejected because it
would expose host filesystem behavior and CLI login state. A second copy
of the Daytona bridge was rejected; the shared transport and catalog
contract are now one module with a provider registry.

**Roadmap alignment**

This extends the existing Apps and Connections provider coverage. It
uses the existing credential, grant, policy, gateway, and audit model.
It does not overlap planned core work.

## What Changed

- Added `scripts/generate-unikraft-tools.mjs` and its tests. The
generator reads the platform and sandbox plugin specifications at commit
`5dd107ea1cd8716b83cb86a83ed2a6ee46f99b5b`, resolves shared parameters,
records source SHA-256 hashes, and writes
`server/src/services/unikraft/operations.generated.json`.
- The catalog has 105 actions: 89 platform operations and 16 sandbox
plugin operations. The server-sent audit event stream is recorded in the
inventory and is not advertised as an action.
- Classification: GET operations and sandbox reads and waits are reads.
Delete, stop, suspend, detach, unpin, and sandbox command execution,
signals, and stdin are destructive. All other operations are writes.
- Added `server/src/services/connectors/unikraft/client.ts` and its
generated catalog. It validates arguments against the generated schemas,
accepts only published metros, rejects path traversal, sends JSON bodies
on GET and DELETE as the specification requires, and verifies the token
with `GET /v1/users/quotas`. A sandbox wait that times out (documented
HTTP 408) returns a still-running result instead of a failure.
- Moved the bounded, credential-redacting HTTP sender and the catalog
contract helpers from `daytona.ts` to `native-rest-client.ts`. Added
`native-provider-catalogs.ts`. `tool-access.ts`, the
`tool-access/catalog` and `token-broker` modules,
`connectors/tool-policy.ts`, and `tool-gateway.ts` now use this registry
instead of Daytona-specific checks. Daytona behavior does not change.
- Added the Unikraft definition source, the generated definition, the
brand mark and manifest entry, and the permission review (`liveProof:
not-run`).
- Added `doc/connections/UNIKRAFT.md` with a sequence diagram,
endpoints, setup, actions, and limits. Updated the connections README,
the permission audit, and both capability maps.
- Tests: definition shape, database-backed gateway reads, writes,
deletes, and sandbox commands for personal and shared grants, default
and per-call metros, rejection of unpublished metros and traversal, Off
policies, revocation, stale-contract blocking, credential export denial,
schema validation for all actions, pinned-transport tests for GET and
DELETE bodies, and a browser setup check.

## Verification

- `pnpm exec vitest run packages/shared/src
server/src/__tests__/unikraft-connection.test.ts
server/src/__tests__/unikraft-http-boundary.test.ts
server/src/__tests__/daytona-connection.test.ts
server/src/__tests__/daytona-http-boundary.test.ts
server/src/__tests__/tool-access-service.test.ts
server/src/__tests__/tool-gateway-service.test.ts
server/src/__tests__/tool-gateway.test.ts
ui/src/pages/apps/AppsConnect.test.tsx ui/src/pages/apps/Browse.test.tsx
ui/src/lib/app-brand-assets.test.ts` plus `connector-tool-policy` and
`tool-catalog-publication`: all passed after the rebase onto the split
tool-access modules.
- `node --test scripts/generate-unikraft-tools.test.mjs
scripts/generate-daytona-tools.test.mjs
scripts/app-brand-validation.test.mjs`: 20 passed.
- `node scripts/check-app-brand-assets.mjs`, `node
scripts/check-maps.mjs`, and `git diff --check`: passed.
- `pnpm --filter @paperclipai/shared typecheck`, `pnpm --filter
@paperclipai/server typecheck`, and `pnpm --filter @paperclipai/ui
typecheck`: clean.
- `npx playwright test --config tests/e2e/playwright.config.ts
tests/e2e/unikraft-connector.spec.ts
tests/e2e/daytona-connector.spec.ts`: 2 passed.
- `node scripts/generate-unikraft-tools.mjs` regenerates the committed
catalog with the recorded hashes.
- Manual: on a local instance, open Connectors, search for Unikraft, and
select **Add key**. Confirm the icon, the password field, the key
guidance, and the default metro select under **Change**.
- Not verified: a real Unikraft account. Live provider read and write
proof is pending.

## Risks

- A Unikraft token acts for the whole organization in every metro.
Unikraft offers no narrower token permissions. Assign only trusted
agents and review action permissions.
- Sandbox actions run arbitrary commands inside the selected instance.
They are classified as destructive.
- A timed-out write can still complete at the provider. The bridge does
not retry writes automatically.
- New metros fail closed until the specification is regenerated and
reviewed. Legacy `*.kraft.cloud` hosts are not reachable.
- The Daytona refactor moves code without behavior changes. All Daytona
tests pass without edits.
- The generated JSON snapshot is large because it holds the provider
input contracts. No migration or lockfile change is required.

## Model Used

- Claude Opus 5.5 (Anthropic), model ID `claude-opus-5-5`, 1M context
window, used through Claude Code with tool use (shell, file editing, web
research, browser tests).

## 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
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-10-22 15:14:26 -07:00
DottaandPaperclip 92cfd701c3 feat: add governed Braintrust app connections (#17141)
Add hosted US and EU Braintrust OAuth and API-key connections through the existing governed MCP system.

Keep reviewed tool risks and catalog review policy in connector modules and a narrow registry. Preserve credential ownership, operator decisions, regional setup and changed-tool quarantine. Include official artwork, setup guidance, focused regressions and sanitized qualification evidence.

US OAuth has bounded live read/write, gateway, reconnect and cleanup proof. Remaining account-method and token-lifecycle qualification gaps are documented.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-21 16:19:58 -05:00
Nicky LeachandPaperclip 313fb265db feat(plugins): invalidate runtimes when connector access changes (#16605)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Runtime preparation depends on access and credential state as well
as tool definitions.
> - Grant, membership, secret, and endpoint changes need committed
invalidation.
> - Their writers must acquire locks before journal fanout can lock
agent rows.
> - This pull request adds access hooks with the corresponding
transaction guards.
> - Plugins can refresh preparation immediately while task-time
authorization remains authoritative.

## Linked Issues or Issue Description

**What happened?**

Grant changes, credential rotation and revocation, company access
changes, and connector endpoint configuration do not request runtime
synchronization. Journal fanout exposes lock inversions between
credential persistence, access cleanup, and connection assignment
writers.

**Expected behavior**

Committed access changes request runtime preparation without polling or
credential values in the journal. Agent-specific secret bindings and new
personal delegations affect their target agent. Company access changes
remain conservative. Provider bookkeeping does not create preparation
work.

**Steps to reproduce**

1. Change an audience, delegation, membership permission, referenced
credential, vault configuration, or endpoint instruction.
2. Expect a committed runtime event in the correct company and scope.
3. Run reconnect, credential refresh, SSH setup, or membership cleanup
concurrently with related writes.
4. Expect both operations to preserve access checks and finish without a
lock-order cycle.

**Additional context**

Final feature extraction from #16503. The earlier slices, #16604, and
the separate delivery-test correction #16871 are merged. This PR is now
the active change against master. The rebase preserves the merged
assignment and definition recipient rules, Unicode selector semantics,
and profile/reference transaction guards.

## What Changed

- Add migration 0356 for grants, audiences, delegation,
membership/permissions, secret bindings, referenced credentials and
vaults, and chat/email endpoint configuration.
- Keep events content-free. Ignore health, delivery, publication, Vercel
verification, and GitHub webhook bookkeeping while retaining credential
and repository-access changes.
- Target agent secret bindings and all personal delegation changes to
their old and new target agents. Coalesce delegation changes per
transaction.
- Lock existing grants before connections and credential persistence in
OAuth and cleanup writers.
- Reject superseded refresh leases before rotating stored credentials.
Ignore lease acquisition and release when access metadata is unchanged.
- Serialize audience replacement, validate membership, and preserve
unchanged audiences.
- Lock membership before permission-only saves and grant before Railway
SSH setup. Individual delegation revocation locks its grant and target.
Whole-grant and membership cleanup lock company recipients before
deleting scoped delegations.
- Lock grants and connection inputs before static-key reconnect writes.
Lock company agents before cascading secret deletion; use a nonblocking
secret lock and bounded retries to avoid a new cycle with credential
writers.
- Add PostgreSQL concurrency coverage for access writers and endpoint
publication/configuration behavior.
- Preserve the owner lock for plugin instance-secret removal; these
secrets cannot use ordinary bindings.
- Align Slack search refresh, callbacks, and disconnect with
grant-before-connection locking. Recheck newly discovered grants without
waiting before provider work.
- Retry complete membership transactions when a credential deletion
candidate is busy. Cover all four cleanup entry points and process
company access in ID order.
- Document final invalidation coverage and task-time authorization
boundaries.

## Verification

- Current head: `78aace55bef7f52bc5742b131e0b3961eb5c0f11`. All 1,061
tests across 23 affected suites pass. The named Slack authorization
integration scenario also passes; it exercises authorization, refresh,
disconnect, and rejection of a late callback. Server/database
typechecks, migration safety and numbering, five-snapshot retention,
feature maps, and diff checks pass. The complete PR diff was reviewed
for secrets and personal data before push. Final acceptance: [CI run
39308303837, attempt
2](https://github.com/paperclipai/paperclip/actions/runs/39308303837) is
green, with 55 successful checks and two optional Storybook skips. The
current-head Greptile reassessment returned **Apex 5/5** at 19:16 UTC on
2026-10-19. Its full summary reports no actionable issues. Security
passed, all threads are resolved, and GitHub reports no merge conflicts.
The reassessment was requested as a standard review after the fixes;
Greptile retained the Apex tier.
- On this head, [CI run
39308303837](https://github.com/paperclipai/paperclip/actions/runs/39308303837)
failed the unchanged adapter-utils HTTP/2 fixture with `EADDRINUSE`
before READY. Its closed probe left a port handoff race. That test and
its gateway are byte-identical on master. No upstream fix was found. The
deterministic fixture correction is isolated in #16888; no adapter test
changes are included here. The failed jobs recovered on retry without a
feature source change. The original failure remains documented here, and
#16888 carries the fixture correction separately. That retry
demonstrates recovery; the held-probe negative control establishes the
port handoff race.
- Rebased onto master `194fc11406`, including merged #16604 and #16871.
Replayed only the access-hook commit. Resolved OAuth, test, and
documentation conflicts while retaining both sets of tests. Migration
0356 preserves the merged assignment/definition recipient rules, Unicode
selector semantics, and profile/reference guards.
- Apex returned 3/5 on `0fb65bc27`. Negative controls reproduce its
Slack delegation and member-cleanup deadlocks (`40P01`) and unwanted
Vercel/GitHub bookkeeping events. Slack grant writers now take their
locks before the connection. A separate late-grant control reproduces
`40P01` without the post-lock recheck; the complete guard passes. All
four membership cleanup commands retry from a fresh transaction when the
credential is busy. Tests verify successful cleanup and no journal rows
from failed attempts. Credential IDs and repository-access changes still
notify runtimes.
- Earlier review corrections remain covered: static-key reconnect and
cascading secret removal each reproduce `40P01` without their guards.
Grant lease acquisition/release is ignored. Secret removal releases
agent locks when a credential writer is busy. Instance-secret removal
retains the owner lock and passes its public plugin API contention
regression. Delegation updates and revocations target old/new agents;
unrelated-peer, coalescing, unchanged-update, and rollback cases pass.
Three negative controls verify the required whole-grant and membership
cleanup guards after narrowing delegation scope.
- Preserve prior acceptance failures: the first rebased 20-suite run
passed 1,025/1,026; its only failure was a draft uninstall fixture
blocking a random peer. Blocking the assigned agent corrected that
assumption, and all 44 access/assignment tests passed. Later, all 1,044
tests across 21 suites, [CI run
39302185527](https://github.com/paperclipai/paperclip/actions/runs/39302185527),
standard Greptile 5/5, and security passed on `0fb65bc27`. That did not
clear the later Apex findings described above. Draft run 38975428081
failed a server shard; its cause was not re-investigated. A later green
run does not establish that earlier cause.
- Local fixture corrections are recorded separately from product
failures: an assignment filename filter initially matched no file; the
actual suite was included in full runs. A delegation fixture omitted its
required creator, and a guard run omitted a query import. The new
global-access cleanup fixture now uses its own user to avoid earlier
fixtures' memberships. All were corrected before publishing their final
iterations.
- Local checks target affected services and real PostgreSQL boundaries.
A full local build and repository-wide test run were not performed.
Hosted CI supplies broader verification. Provider responses in tests are
controlled; live provider behavior was not qualified.

## Risks

Migration 0356 adds triggers without changing table schema. Apply it
through the normal migration flow. Most access changes retain
synchronous company-wide invalidation. Company fanout takes O(eligible
company agents) locks and journal rows, without a fanout ceiling or
mutation quota. Agent secret bindings and individual delegation changes
retain narrower recipients. Events contain no credentials.

Physical removal of non-instance secrets takes ordered locks on all
company agents before cascading into bindings. This costs O(company
agents) locks even for an otherwise unreferenced secret. Instance
secrets cannot use ordinary bindings and retain their owner lock. A busy
secret lock releases the transaction guards and retries up to three
times. Continued contention returns a retryable conflict. Provider
deletion stays outside that transaction; a retry resumes removal of an
already disabled secret.

Membership cleanup uses nonblocking credential guards and retries the
full membership transaction. Slack search adds two grant queries, scoped
to the subject and connection. Its retries occur before provider work or
credential persistence. Each retry loop is limited to three attempts.
Invalidation requests preparation; task-time authorization and provider
session activation remain authoritative. Provider calls use fixtures; no
live provider qualification is claimed.

## Model Used

OpenAI Codex, GPT-6, with reasoning, repository inspection, code
execution, and testing. The exact deployment model ID and context window
are not exposed in this session.

## 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-19 12:49:11 -07:00
DottaandPaperclip 2cbca4ceb0 fix: retain channel tools across task continuations (#16806)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat channels give an agent tools for its assigned task.
> - Each later run must resolve the task and its accepted requester
again.
> - Some native runs store the task in a database column without the
older JSON fields.
> - Tool discovery read only the JSON fields. GitHub calls also required
a new inbound comment.
> - This pull request uses the durable task binding and accepted request
history.
> - Later runs retain their channel tools while current access checks
still apply.

## Linked Issues or Issue Description

**What happened?**

A GitHub task can find `begin_review` on its first run, then receive an
empty tool list on a later native run. If discovery is repaired alone, a
call can still fail because the later run has no new inbound comment.
Slack and voice tool access also read the older JSON task fields.

**Expected behavior**

A later run for the same task can find and call its assigned channel
tools. The current requester, task, company, agent, endpoint, and access
rules must still allow the call. Revoked access must fail.

**Steps to reproduce**

1. Start a GitHub task and accept its linked requester.
2. Confirm that the runtime can find `begin_review`.
3. Start a later native run with `nativeIssueId`, accepted parent
identity, and no JSON task ID or new wake comment.
4. Search for `begin_review` again. Before this change, the search
returns an empty list.
5. Repair discovery alone and call `read_pull_request`. Before the
request-history fix, the call fails with no active conversation
capability.

**Paperclip version or commit**

Reproduced in source tests before this patch. The branch includes master
at `fa50cab5685b9cdbb26ad9c610cc5b6c373d3ff4`.

**Additional context**

This is a core run-binding bug. The tests use PostgreSQL and synthetic
provider responses. They do not send live reviews, Slack messages, or
phone calls.

## What Changed

- Resolve run task IDs from durable columns, with legacy JSON fields as
a fallback.
- Use the same binding in the gateway, access policy, identity service,
and channel runtime preparation.
- Recover accepted channel request history across later runs. Keep
company, task, agent, and requester boundaries.
- Recover older wake sources through verified parent runs, including
after same-user board follow-ups. Clear the board message’s own legacy
wake fallback. Keep cycle checks without a fixed limit on valid task
history.
- Retain the GitHub origin after a board comment from the same accepted
user. Skip GitHub origin lookup results from other providers.
- Keep ordinary board tools available when the requester changes. Accept
legacy user comments without an author-type field. Still reject explicit
malformed task IDs.
- Prevent a later failure reply from replacing an earlier final GitHub
answer. Recheck this rule under the publication lease.
- Rotate the native tool contract to replace retained sessions with an
older tool list.
- Add continuation, publication, revocation, and boundary tests. Update
the access and feature maps.

## Verification

- Red: the later GitHub assigned-tool search returned an empty list
before the binding fix.
- Red: the later GitHub read failed with no active conversation
capability before the request-history fix.
- Green: runtime MCP discovery, GitHub read/begin/submit review, and
response publication pass for monitor and same-user board continuations.
- Green: Slack history, retained access controls, revocation, and voice
gateway continuation pass.
- Green: 35 channel, failure-publication, legacy-origin, long-history,
and provenance tests pass. Both review findings had failing tests before
their fixes.
- Green: 107 gateway, operation-credential, identity, and provenance
tests pass. These cover both first-run CI failures without changing
their tests.
- Green: 122 runtime, discovery-policy, and native-session tests pass; 2
unrelated tests are skipped.
- Map checks and whitespace checks pass.
- Updated to master in `cfcaba22628772d7fe1fb32b57ff7031c7072781`. The
sole conflict was two tests added at the same location. Both the
continuation test and the publication 403/401 test are retained.
- Current local verification: all 179 gateway, credential,
requester-identity, access-policy, runtime-context, and session-resume
tests passed. Repository typecheck and build passed. Map and whitespace
checks passed.
- The new review regression first returned no source for a same-user
board follow-up over legacy wake metadata. After the repair, all 27
provenance and channel cases passed. The combined GitHub
discovery/read/begin/submit path and revoked access are covered.
- The broader local channel run passed 176 cases and failed four
timing/setup cases: a 15-second Slack authorization timeout,
webhook-verification polling, a Slack acknowledgement deadline, and
Discord setup polling. All four passed in isolation without source,
assertion, or deadline changes. The earlier failure record is retained;
the exact load/order cause is not established. Full CI must pass on the
latest commit.
- Current head: `7b9a08dcbc7b8140b589742f136944270b0496bb`. Repository
typecheck and build pass on this commit. Greptile completed on this
exact commit with 5/5; all four review threads are resolved. The
final-head [CI
run](https://github.com/paperclipai/paperclip/actions/runs/39278921653)
passed: 55 checks passed and 2 intentionally skipped, with no failures
or pending checks. This includes the full sharded test matrix, browser
tests, typecheck, build, and Runner verification. Results were delayed
during the [GitHub Actions
incident](https://www.githubstatus.com/incidents/8tzbpcnl75jp). An
additional unsharded local full test run has not completed; the
completed full-suite evidence is CI.
- Earlier verification: the first PR commit failed two server suites.
Those failures were fixed and verified before this update. The original
4 GiB sandbox could not complete full local typechecking or tests; the
current checkout completed typechecking and build. The full test suite
runs through the CI shards. No full local test-suite pass or live
provider delivery is claimed.

## Risks

- Request history can restore the wrong authority if its scope is too
broad. The resolver checks each accepted parent against the task,
company, agent, and requester. Tests cover invalid and cyclic history.
- The native contract change starts a new provider session for older
contracts.
- No database migration or public API schema changes are required. Each
tool call still checks live access.

## Model Used

- OpenAI Codex, GPT-6 family. The runtime does not expose the exact
deployment model ID or context-window size. The agent used reasoning,
repository tools, code edits, and local test execution.

## 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-19 11:20:39 -05:00
DottaandPaperclip 669d329f25 perf(slack): avoid unused catalog revision scans (#16630)
Slack catalog discovery now checks live task, user, endpoint and credentials without calculating an unused compatibility revision. Full authority callers retain the unchanged revision and search-token path.

Validation: 44 affected cases, full repository typecheck/build, current-head full CI/E2E and security checks, Greptile Base 5/5 with no unresolved findings. Identical production catalog output with revision statements reduced from two to zero in real-PostgreSQL comparisons. Hosted latency acceptance remains pending.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-16 22:21:03 -05:00
DottaandPaperclip 3db33c131e perf(slack): overlap endpoint preparation and narrow credential reads (#16593)
Prepare Slack endpoints in pairs with a per-call concurrency limit of two, and resolve only the current bot token for live tool authority. Preserve candidate-order errors, active-sibling settlement, credential rotation and authorization revocation.

Verified with real PostgreSQL regression controls, full repository CI/E2E, security checks and current-head Greptile Plus5/5 with no unresolved findings.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-16 16:05:46 -05:00
DottaandPaperclip 185483e090 perf(slack): keep authorization revision rows inside PostgreSQL (#16527)
Compute Slack authorization revisions in one PostgreSQL statement while retaining all existing scope and invalidation inputs. Return one ordered digest instead of materializing retained profile rows in Node.

Validated with 19 affected cases, full typecheck/build, final-head CI/E2E/Superagent, and Apex 5/5.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-15 22:31:46 -05:00
DottaandPaperclip 5ec93dae01 fix(connectors): avoid redundant run preparation discovery (#16461)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Run preparation selects connector skills and tools under current
permissions.
> - An assignment check can build an unrelated company tool catalog and
wait for a shared discovery slot.
> - Native startup repeats assignment discovery to obtain static tool
definitions.
> - Slack also locks and reconciles an unchanged catalog, then repeats
task authorization.
> - This pull request removes that redundant startup work and preserves
live checks at tool execution.
> - The benefit is less preparation work, less contention, and unchanged
permission and approval enforcement.

## Linked Issues or Issue Description

Related: #16454 (detailed preparation tracing), #16425 (workspace
preparation performance).

**What happened?**

Connector configuration added avoidable work to run preparation. Browser
Use assignment authorized the whole company catalog, including other
connector families. Four connector resolvers ran in series. Native
controller startup repeated all assignment resolution when any connector
skill was pinned. Slack reconciled an unchanged catalog under an
advisory lock and checked task authority twice.

**Expected behavior**

Prepare only the connector data needed by the run. Reuse static tool
definitions from pinned skills. Preserve current company, assignment,
identity, profile, policy, grant, and approval checks when an operation
executes.

**Steps to reproduce**

1. Configure Browser Use and an unrelated MCP catalog with 500 tools for
one company.
2. Resolve Browser Use resources for an authorized task. The old path
reads and authorizes the unrelated catalog.
3. Occupy both full discovery slots. The old assignment check waits for
those slots.
4. Resolve a linked Slack task repeatedly with an existing current
catalog. The old path still acquires a catalog lock and repeats
authority checks.

**Paperclip version or commit**

Base: `68a09dcb5f50e3fb6ceaaeac2706d96db97fc9b3`.

**Deployment mode**

Observed in hosted native runs. The local reproduction uses a source
checkout and real embedded PostgreSQL.

## What Changed

- Restrict Browser Use catalog reads and policy decisions to active
Browser Use connections. Preserve guest restrictions, reviewed catalog
filters, live grants, and deterministic resource order. Keep assignment
checks out of the full discovery queue.
- Resolve the four independent connector families concurrently. Wait for
outstanding work to settle before propagating a failure, and retain
registration order.
- Register native direct connector tool definitions from pinned
connector skills. Keep live assignment resolution and governed execution
on every tool call.
- Compare Slack catalog hashes before reconciliation. Current catalogs
skip the catalog transaction and lock. Check task authority once after
current profile checks. Initial setup and upgrades retain locked
reconciliation and checks before and after it.
- Precompute immutable bundled Slack descriptor hashes. Preserve
disabled entries, profile state, removed bindings, and review metadata.
- Document the startup paths and add focused contention, revocation,
catalog upgrade, and failure-settlement regressions.
- Repair a pre-existing CI guard false positive: the filename
`docker-compose-secrets.test.mjs` matched `secrets.`. Check GitHub
secret expressions instead, with dot, bracket, and whole-context
controls. No workflow changes.

## Verification

- Conflict resolution: merge `b1566ca494f4af6e8d4418fa37393c5caee02582`
from master into head `55140b1609ae7bd21a038eb75a48c2683299e4b4`.
Combine both secret-expression guards and regression cases. Preserve
current workspace, native recovery, and Daytona changes. All 467 policy
tests, 787 focused native/connector/Browser Use tests, and server
typecheck passed locally after integration. Fresh full CI passed all 55
checks on this head, with two optional Storybook jobs skipped. Greptile
reviewed this exact head at 5/5 with no unresolved threads.

- `pnpm -r typecheck` — passed.
- `pnpm build` — passed.
- Focused native startup, connector concurrency, and AgentMail suites —
763 tests passed.
- Complete Browser Use suite — 33 tests passed. Focused Slack catalog,
linked task, retained provenance/revocation, and pinned native tool
tests passed. The complete runner tool authority suite passed (26
tests). The 1,337-case chat suite passed 1,335 tests and had two
failures: the original new transaction-count assertion and a 15-second
timeout in the publication-batch case. Both cases passed an isolated
rerun. The publication timeout occurred during concurrent local checks;
the passing rerun does not erase it. CI must still pass the chat shards.
- The first focused run found two incorrect new assertions: policy
evaluation performs a second catalog lookup, and an explicit allow
policy overrides a profile default. The tests now distinguish the scoped
catalog query and revoke the governing policy. The focused Browser Use
rerun passed all 33 cases after these assertion fixes.
- Full-suite test verification used the CI shards of `pnpm test:run`.
Local runs focused on the changed boundaries; the complete repository
test command was not duplicated locally.
- `node --test '.github/scripts/tests/*.test.mjs'` — all 467 policy
tests passed. The CI failure reproduced on the unchanged base guard
before this correction. Actual GitHub secret expressions still match the
guard.
- CI on the final head passed all chat shards, typecheck, build, Runner
checks, browser shards, and other test lanes. One existing
workspace-runtime case hit `EADDRINUSE` for a randomly selected test
listener in server shard 1/12 (1,162 tests passed in that shard). The
shard passed its single retry on the same SHA with no source changes.
The first failure remains recorded here. Previous reviewed head
`7191ac40691ddb1ef38b86665c95cc14c57ea390`: all 55 checks passed, two
optional Storybook jobs skipped, and no pending or failed checks.
Greptile is 5/5 on this head with no unresolved review threads. The
external security scan passed.

Local before/after measurements use the old and new implementations
against the same fixture. Both paths are warmed. Seven samples alternate
execution order. The database is real embedded PostgreSQL. No latency is
injected. These measurements do not establish hosted speed.

| Local path | Before median (range) | After median (range) | Work
reduction |
| --- | --- | --- | --- |
| Browser Use assignment with 500 unrelated MCP tools | 44.020 ms
(33.994–107.328) | 26.502 ms (20.385–99.037) | 26 → 22 statements;
unrelated catalog and discovery queue removed |
| Slack assignment with current catalog and linked responsible user |
49.723 ms (43.624–80.653) | 22.141 ms (19.781–30.818) | 5 → 2 database
transactions; no catalog lock on the current path |

The contention regression fails against the old implementation after a
bounded five-second wait, then passes against the optimized
implementation. It occupies the real global discovery scheduler and
verifies that Browser Use assignment completes without releasing those
slots. It records catalog SQL to verify connection scope. Revocation
cases remove policy, catalog availability, and grants between calls.
Existing Slack integration cases exercise retained provenance, removed
profile bindings, identity revocation, approved writes, and current
responsible-user restrictions.

## Risks

- Pinned native tool definitions can remain visible after access is
revoked. They confer no authority. Invocation rechecks current
assignments and fails closed before an operation executes. Newly
available connector families still require a newly admitted skill
selection.
- Concurrent resolution can increase instantaneous database reads to
four connector families per configuration call. It is a fixed bound.
Outstanding work settles before a failed preparation returns.
- Slack skips reconciliation only when all bundled version hashes and an
existing profile match. Missing or changed definitions still use the
existing locked path. Operator revocations remain effective.
- This PR addresses connector preparation. Workspace transfer, provider
startup, copyback, and queue delay can still keep total latency above
the user's goal. Hosted improvement needs a deployed before/after trace.
- No schema, lockfile, workflow, telemetry event, or authorization cache
changes.

## Model Used

OpenAI GPT-6 (Codex), with reasoning, repository inspection, code
execution, and GitHub tools. The runtime does not expose the exact
serving model ID or context window.

## 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-15 14:08:01 -05:00
DottaandPaperclip 25b16e65fc fix(observability): detail workspace and connector preparation (#16454)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The server prepares a repository, sandbox workspace, and connector
access before an agent can reply.
> - Existing traces measure large preparation phases but leave important
work inside those phases unclear.
> - Repository source materialization and Browser Use discovery can do
more work than their callers suggest.
> - New detail must preserve access checks, run ownership, and the
existing work order.
> - This pull request adds fixed OpenTelemetry spans inside those
operations.
> - Operators can use one deployed trace to select the next performance
fix.

## Linked Issues or Issue Description

Refs: #16419, #16425, #16428.

**What existing behavior does this improve?**

Startup traces for server workspace preparation, native sandbox
synchronization, and connector assignment resolution.

**Current behavior**

Workspace and connector aggregate spans can take many seconds. The trace
does not separate private source cloning, seed reuse, archive work,
progress persistence, or each connector resolver. Browser Use resource
selection builds the full authorized tool catalog. The configuration and
native backend can each resolve connector assignments.

**Proposed behavior**

Show the awaited work as fixed child spans. Separate discovery queue
wait from catalog construction. Preserve the initiating run context when
another run releases a scheduler slot. Add no new lifecycle event writes
for workspace detail callbacks.

**Reason and benefit**

Operators need evidence about the hosted critical path before another
performance change. These spans distinguish filesystem work, provider
transfer, authorization, transaction entry, locks, and reporting
overhead.

**Breaking changes**

None. Authorization, query order, transaction ownership,
synchronization, existing progress events, and task results retain their
contracts. The change adds opt-in Observability spans under the existing
OTLP endpoint gate.

## What Changed

- Trace private source directory setup, Git credentials, clone,
requested ref, source identity, and checkout publication.
- Trace sandbox source capture, seed cache/replay, shallow clone and
archive, overlay copy/archive, verification, upload, warm stamps, and
descriptor persistence.
- Separate existing awaited progress reporting from useful workspace
work. Keep new detail callbacks trace-only.
- Trace each connector resolver and Browser Use catalog/grant work.
Split discovery queueing, descriptor sources, and policy evaluation.
- Trace Slack authority, credential reads, catalog synchronization,
transaction entry/settlement, and advisory locks.
- Update the real filesystem staging trace expectations and the
Honeycomb investigation guide.
- Add a real scheduler regression for a queued job released by another
run. Assert run ownership, parent spans, and exactly one completed queue
span.

## Verification

- Passed: server and adapter-utils TypeScript checks (`pnpm --filter
@paperclipai/server exec tsc --noEmit` and `pnpm --filter
@paperclipai/adapter-utils exec tsc --noEmit`).
- Passed: 252 checks across 9 focused files. These cover real filesystem
staging, native workspace synchronization, trace ownership, endpoint
gating, and workspace preparation.
- Passed after review: 26 trace-context, tracing-failure, and
discovery-scheduler checks across 3 files (these overlap the first run).
The new queued-discovery regression fails when context binding is
removed and passes after restoration. An initial submillisecond
timestamp assertion was replaced with explicit span-completion order to
avoid SDK clock precision assumptions.
- Passed on implementation commit
`0e68968a4bd61001893d833f281f12bb110edbe1`: `pnpm -r typecheck` and
`pnpm build`. The later commit updates only an engine test expectation.
- The first CI workspace lane found an old engine trace-tree
expectation. It expected the earlier span set. The updated assertion now
checks the new detail spans, their parents, and single completion. Its
targeted executor check passes.
- The full test suite, build, release registry, and end-to-end gates
pass in CI on final head `40e37d89ef679109d60a96bb5731a0616efeaa43`: 55
passing checks and 2 optional Storybook skips. The full suite was not
duplicated locally after the focused run.
- Greptile reviewed the final head at 5/5. No unresolved review threads
remain.
- After deployment, filter Honeycomb by the hashed run ID and verify
`service.version`. Inspect `heartbeat.prepare.workspace`,
`runtime_selection.workspace_sync`, and the connector assignment
parents. The guide in `doc/observability.md` explains each new family
and the nested intervals.
- No hosted run has used this new instrumentation yet. Local checks
cannot establish hosted latency improvement.

## Risks

- Tracing adds spans when an operator configures an OTLP endpoint.
Detail remains capped at 16 spans per phase per execution attempt.
- Parent and child durations overlap. The documentation explains how to
avoid counting them twice.
- A discovery job can start in another run's scheduler continuation. The
bound callback preserves the initiating async context.
- New spans export fixed names and the existing hashed run ID. They add
no paths, repository URLs, connector resource IDs, credentials, tool
schemas, or exception text.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tool use, and code
execution. The exact served model ID and context-window size are not
exposed in this session.

## 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-15 12:21:32 -05:00
DottaandPaperclip f0e12c8519 Add managed Slack setup with an independent own-app path (#15679)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Slack connects a person to an agent through an installed app and a
verified identity.
> - Independent installations must remain usable without Paperclip Cloud
or manager credentials.
> - Approved Cloud deployments can use Slack manager grants to create
and install each agent's app.
> - Both paths should share credential storage, identity checks,
recovery, and the existing runtime.
> - This pull request adds gated managed setup and keeps independent app
setup under Advanced.
> - It also makes ongoing connection settings and personal test messages
easier to use.

## Linked Issues or Issue Description

**Subsystem affected**

Slack setup, connection settings, tenant credential storage, and the
Cloud connector handoff.

**Problem or motivation**

Approved deployments need an installation flow without pasted
configuration tokens. Open-source users must retain their independent
Slack app flow. A connection manager also needs a simple way to check a
bot from Settings.

**Proposed solution**

Use the managed path when the instance is configured to support it.
Choose agent and Connect are the two visible stops. Continue starts
authorization or installation. Use your own app remains under Advanced
before creation. Save personal manager grants by company, Paperclip
user, Slack user, workspace, and manager app. Reuse only verified
identities for test messages. Unknown identities must complete a private
Slack connection challenge before linking and receiving the test DM.

**Alternatives considered**

A shared bot would change each agent's Slack identity. Requiring Slack
CLI or a hosted service for self-hosted users would remove independent
installation.

**Roadmap alignment**

This maintainer-requested change improves Connected Apps and
experimental Agent Chat. It adds provisioning and management controls to
the existing Slack runtime.

**Additional context**

The companion Cloud broker profile is a separate deployment
prerequisite. Managed setup remains gated. Existing-app adoption is
deferred.

## What Changed

- Extract Slack registration, provider requests, completion,
customer-owned setup, managed setup, and personal manager grants into
focused services. Preserve the compatibility facade and independent
removal cleanup.
- Add company-scoped manager grants and a registration reference through
an additive, idempotent migration after current master. Keep runtime
credentials separate from app-registration secrets.
- Add authenticated manager authorization, sealed handoff, serialized
refresh and revocation, app creation, managed installation, and
installer-bound OAuth fallback.
- Preserve creation intent, block automatic uncertain recreation, save
credentials before downstream checks, and validate app, workspace, bot,
scopes, and installer identity.
- Add the two-stop production wizard and ordered stories. Keep the
own-app, manual, existing-app, and legacy-draft paths.
- Simplify Settings. Open Slack configuration targets the saved app. The
test-message action has its own row. Remove the old manual-avatar
section, channel-message section, and broken permissions link.
- Add paginated account discovery and a private connection challenge for
unknown accounts. Expired invitations stop waiting and offer a new
private invitation. Save send receipts before provider dispatch and
preserve confirmed delivery when activity logging fails.
- Reinstall the saved managed app on explicit reconnect, replace revoked
credentials, and resume completion. Persist reconnect intent and
duplicate-request receipts without creating another app.
- Update provider browser tests, recovery tests, secret redaction, setup
documentation, and the agent prompt. Preserve current master's durable
verification scheduling.

## Verification

- Full workspace typecheck and repository build passed on `56d389d47a`.
The subsequent reconnect retry fix in `288364eada` also passed UI
typecheck and UI build.
- 114 focused Slack registration cases and 13 production managed-wizard
cases passed, including fresh-token reconnect, retry after installation
failure, and duplicate reconnect requests.
- All nine affected Slack browser cases passed against the production UI
and a disposable fixture server. They cover managed setup, automatic
setup, own-app selection, refresh, recovery, mobile behavior, and
connection settings.
- Eight focused real-database test-message cases passed. They cover a
private ownership challenge, saved grant reuse, account pagination,
revoked and conflicting links, workspace mismatch, disabled DMs, revoked
membership, audit failure, ambiguous dispatch, and secret canaries.
- UI token gates and the production Storybook build passed.
- Greptile reviewed exact head
`288364eada5d9c114fad991ff634612639d06672` at 5/5 with no actionable
findings or unresolved review threads.
- The full repository test suite and current-head CI are running. Their
final results will replace this line before merge.
- Earlier live feature previews created two bots in the authorized
Paperclip Slack workspace and reused one personal manager grant. Local
managed Continue created and installed a bot without a configuration
token or a separate Add to Slack action. Avatars, welcome DMs, signed
callbacks, and direct replies were observed. A Settings test DM also
arrived in the signed-in user's Slack account.
- Earlier staging thread qualification required manual publication
recovery for one bot. Current-head live qualification remains required
before enabling the production default. Fixture results do not establish
Slack approval behavior in other workspaces.

## Risks

- Personal manager tokens can create apps. They stay in scoped vault
entries. The manager client secret stays at the broker. Company,
actor/session, origin, and app identity checks apply throughout setup.
- The additive migration must also work on qualification instances that
applied earlier branch migrations. Table, column, index, and constraint
creation is idempotent.
- Creation and message timeouts can leave uncertain outcomes. Saved
request IDs prevent automatic duplicate dispatch.
- Unknown Slack identities must receive and complete their private
challenge while signed in. Account selection alone does not grant
Paperclip permissions. Existing revoked or conflicting links are not
overwritten.
- A development-only manager transport uses an explicitly configured
private credential file for local qualification. Production ignores this
transport; no manager credentials are bundled with open source.
- Managed rollout requires Slack approval, the companion broker
deployment, configured secrets, and final live qualification. Removing a
connection does not delete its Slack app.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, code execution, and browser
tools. The session does not expose the exact serving 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
- [ ] 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
- [ ] 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-12 15:34:02 -05:00
DottaandPaperclip 19e9facc5b perf(chat): wake delivery queues from commits and deadlines (#15802)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat connectors store incoming messages and outgoing publications in
durable queues.
> - The app checks these queues every second, even when they are empty.
> - Empty scans keep the database active and hinder instance sleep.
> - This pull request wakes three queue workers after transactions
settle and at known retry or recovery deadlines.
> - Empty queues stop scheduling checks. Existing rows retain their
ordering, retry, and recovery rules.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Idle database activity from incoming chat deliveries, outgoing
publications, and Slack upload receipt recovery.

**Subsystem affected**

`server/` — chat delivery and background work scheduling.

**Current behavior**

The app's one-second chat timer scans the three queues together with
provider and action maintenance. Empty queues continue to query
PostgreSQL.

**Proposed behavior**

Register three independent workers with the existing delivery
coordinator. Producers announce work inside their database transactions.
Commit wakes the corresponding worker. Startup restores outstanding
work; persisted retries and stale claims supply the next deadline. An
empty queue has no recurring scan.

**Reason and benefit**

Remove avoidable queue reads without requiring a new table, an external
scheduler, or a persistent PostgreSQL listener.

**Breaking changes**

No schema or public API change. Work notifications are scoped to the
app's shared database owner. Direct SQL and independent database roots
do not send these notifications; startup still scans durable work.

**Additional context**

Refs #15625, #15750, and #15757 for the preceding sleep work. Related:
#15153 reduces chat query allocation while retaining polling. This PR
changes when the three queue workers run; it does not add query caching.

## What Changed

- Register independent incoming delivery, publication, and Slack receipt
workers on the shared scheduler.
- Add transaction work signals at queue writes, endpoint state changes,
and action transitions that unblock publications. Keep provider I/O
outside the added transactions.
- Restore deadlines from durable retry times, abandoned claims, and
publication lease expiry. Share publication and receipt eligibility
rules between dispatch and deadline queries. Respect incoming
conversation order and lifecycle dependencies.
- Exclude publications blocked by unresolved Slack tool sends. Wake them
when the tool receipt changes.
- Wake publication dispatch when an endpoint send finishes so free slots
refill. Preserve per-endpoint concurrency, conversation order, and
conservative handling of uncertain sends.
- Wake receipt recovery when a stale publication becomes
`delivery_unknown`, and wake queues when a provider connection recovers.
- Commit interaction publications with their callback tokens so dispatch
cannot see an incomplete card.
- Keep provider runtimes, other action outboxes, milestone and
wake-notice projection, Teams protocol maintenance, GitHub recovery, and
Slack session synchronization on their existing maintenance cadence.
This PR does not make the whole chat subsystem idle.
- Update the instance sleep inventory with this partial migration and
its remaining work.

## Verification

- All 1,225 PostgreSQL chat integration cases passed across the three
hosted chat shards. These cover retry and lease deadlines, blocked
followers, unresolved Slack sends, provider recovery, commit visibility,
and endpoint slot refill.
- 32 local app-wiring, queue-worker, and delivery-coordinator tests
passed after updating the wiring assertion for event-driven dispatch.
Fake timers cover an hour of idle time without queue scans.
- Related publication, interaction, receipt, and wake-notice tests
passed locally. The 13 interaction integration cases include atomic
rollback when callback-token storage fails.
- Local `pnpm typecheck`, `pnpm build`, and final server typecheck
passed. All hosted checks passed on the final commit, including build,
typecheck, test shards, release registry checks, and the canary dry run
(54 successful checks; two Storybook checks skipped for this backend
change).
- The last local PostgreSQL rerun was skipped because the embedded
database startup probe failed after five attempts. The hosted PostgreSQL
cases ran successfully; their skips only partition cases across shards.
- `git diff --check` passed. Greptile is 5/5 on the final commit with no
unresolved findings.

## Risks

- Every producer that makes queued work eligible must send a transaction
work signal. The tests exercise commit visibility, concurrent wakes,
worker failures, and restart recovery. Future direct SQL writers must
participate in this contract.
- The existing database work-signal layer reconciles uncertain
transaction outcomes. This PR adds no work-signal table or schema
migration.
- Provider and action maintenance still polls. Further changes are
required before an idle chat-enabled instance can sleep.
- Tests use real PostgreSQL with simulated provider responses; they do
not send messages through live provider accounts.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, tool use, and code
execution. The exact serving model ID and context-window size are not
exposed in this session.

## 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
- [ ] 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-10 09:13:44 -05:00
Dotta 43212cb2b7 fix(slack): require result and review updates in conversation prompts (#15611)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - People can ask an agent to do work from a Slack thread.
> - The agent must return results and review requests to that
conversation.
> - The current prompts explain reply format but do not require these
updates.
> - This change adds one set of instructions to initial prompts and
later turns.
> - Users can see the result and the action needed for review in Slack.

## Linked Issues or Issue Description

**What happened?**
An agent can save results or a plan in Paperclip without telling the
user in Slack that the result is ready or that review is required.

**Expected behavior**
The agent reports results in the originating conversation. If review is
needed, it saves the required interaction and tells the user what to
review and how to act.

**Steps to reproduce**
Start work in a Slack thread. Have the agent prepare a plan that needs
approval or produce a deliverable. The prompt does not explicitly
require a result or review update in that thread.

Related: #15579 adds task links to Slack replies. This change covers
results and review requests, including later turns.

## What Changed

- Add shared instructions for result and review updates.
- Include the instructions in initial Slack guidance and per-turn
guidance.
- Keep the normal approval gates, delivery checks, and duplicate-message
rules.
- Add tests for channel and direct conversations, and for fresh and
resumed native and CLI turns.
- Update the Slack skill documentation.

## Verification

- Passed: guidance and heartbeat context tests (65 tests in two files).
- Passed: `git diff --check`.
- Workspace typecheck and build could not complete because this sandbox
has no `cargo` binary.
- The full local test run was stopped due to the sandbox memory limit.
GitHub CI runs the full checks.
- GitHub CI and automated review are pending.

## Risks

- Low risk. This change updates prompt text and tests. It does not
change transport or permissions.
- Prompt instructions guide agent behavior. They do not guarantee that
Slack delivery succeeds.

## Model Used

- OpenAI GPT-6 (Codex). Used reasoning, code editing, and command tools.
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
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-10-09 20:16:24 -05:00
DottaandPaperclip 71af2fbc3b fix(slack): teach agents how people connect their accounts (#15576)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Slack connections let people talk to an agent with their own
Paperclip permissions.
> - Each bot has a saved command that starts account linking.
> - The Access page explains this flow, but Slack agent turn context
omitted it.
> - An agent could guess the command or confuse channel membership with
Paperclip access.
> - This pull request gives agents the saved command and account
confirmation instructions.
> - People can ask the agent how to join without changing access
controls.

## Linked Issues or Issue Description

**What happened?**

Slack agent context explained messages, tools, and questions. It did not
explain how a teammate can connect an account. The saved slash command
can differ from the current agent name.

**Expected behavior**

Give the saved bot command, such as `/research_ops connect`. The
teammate runs it themselves. They sign in through a private confirmation
link. A new company member must receive admin approval before account
confirmation. The connection manager can copy instructions from Access →
Invite people.

**Steps to reproduce**

1. Configure a Slack bot with a custom slash command.
2. Rename its assigned agent.
3. Inspect a fresh or resumed Slack task prompt. Before this change, it
contains no account invitation instructions or saved connect command.

**Paperclip version or commit**

Base: `d6df12cef69fcaf2d2fe66a393168931d5b8b4e7`.

**Deployment mode**

Applies to local and hosted Slack chat connections. Deterministic tests
used a local isolated database. The new model probe has not run against
a live Slack bot.

Related work: Refs #15413 and #13638. This fixes agent guidance for
their existing account-linking flow. It adds no new membership system or
invitation endpoint.

## What Changed

- Read only the saved public slash command from the company-scoped
conversation endpoint. Supply it only to the assigned agent for Slack
turns with an active or verifying connection.
- Validate the command with the shared Slack configuration schema. Refer
to Access → Invite people when it is missing or invalid. Never guess
from the current agent name.
- Explain personal account confirmation, link expiry, and company
membership approval on fresh and resumed turns. Distinguish channel
invitations from Paperclip access.
- Add deterministic guidance regressions, a manual invitation model
probe, and setup documentation.

## Verification

- Passed: 63 tests in `heartbeat-context-summary.test.ts` and
`heartbeat-chat-task-link.test.ts`.
- Passed: four real-heartbeat regressions in
`heartbeat-slack-invitation.test.ts`. They check the saved command after
an agent rename, a persisted resumed session, full and compact prompts,
missing-command fallback, inactive endpoints, and a different assigned
agent. They also reject caller-supplied command fields and exclude other
setup metadata.
- Passed: the isolated `chat-channels.integration.test.ts` case
`discovers a Slack connect identity without starting work or granting
access`. It covers the private link, duplicate connect requests, and
nonmember access requests without a membership grant.
- Passed: `pnpm --filter @paperclipai/server typecheck` and `pnpm
--filter @paperclipai/server build`.
- Passed: `pnpm test:slack-connector --list` and `git diff --check`.
- Passed: repository `pnpm -r typecheck`, `pnpm build`, and `pnpm
check:token-gates`. Typecheck required local IPC access for the
migration check.
- Passed: final-commit CI, with 54 successful checks and two optional
Storybook checks skipped. CI includes all server, chat, workspace,
serialized, Runner, and browser test shards, typecheck, build, and
canary dry run.
- The full local `pnpm test:run` was started. It was stopped after full
CI passed; it had no final local summary. The focused invitation checks
passed locally. Do not count the interrupted local run as a full-suite
pass.
- Greptile gave the exact final commit
`f37e52bde621ef7f5b2bb345074d53345f8e4ee9` a 5/5 score. Both review
findings were fixed and their threads resolved.
- The new `invite-person` model probe is manual. These deterministic
results do not establish a live model or Slack acceptance pass.

## Risks

- Model guidance cannot prove that a person joined. The existing
account-linking and membership checks remain authoritative.
- Legacy rows without a saved command use the Access page fallback.
Invalid command text is excluded from the prompt.
- The query selects only the public command. It does not expose
registration secrets, tokens, or personal confirmation links.
- No schema changes, new provider requests, permission grants, or
telemetry changes.

## Model Used

- OpenAI GPT-6 through Codex. The exact backend variant and context
window are not exposed in this session. Used reasoning, repository
inspection, code editing, and test execution.

## 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-08 10:28:14 -05:00
DottaandPaperclip d66acb7ac1 feat: automate Slack bot app setup and installation (#15413)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat connectors give each agent a customer-owned bot and task-backed
conversations.
> - Manual Slack setup requires app creation and copying durable
credentials.
> - Operators need a shorter setup that an assisting agent can use
safely.
> - This pull request creates the app through Slack's Manifest API and
installs it through OAuth.
> - Durable registration state supports recovery without creating
another app.
> - A four-screen wizard, automatic avatar upload, and OAuth account
linking reduce setup work.
> - Connector settings and per-turn tool guidance support daily use
after installation.

## Linked Issues or Issue Description

**Subsystem affected**

Native Slack bot setup, company secret storage, chat connector
management, and agent tool guidance.

**Problem or motivation**

New Slack bots require manual app creation and copying a signing secret
and bot token. Interrupted setup can create duplicate apps. The setup
and management screens contain unnecessary controls. Agents also need
guidance for native questions, files, thread replies, and governed Slack
actions.

**Proposed solution**

Use a temporary app-configuration access token to create a
customer-owned app. Save durable secrets in the vault. Bind OAuth to the
initiating actor, company, endpoint, registration revision, scopes, and
configured origins. Preserve manual and existing-app recovery. Link the
installing user's account, send a welcome DM, and advance from saved
server evidence. Keep request-URL recovery instructions available if
automatic connection detection waits.

**Alternatives considered**

The Slack CLI adds installation requirements. Socket Mode changes
transport. A shared Paperclip-owned app changes app ownership. These
alternatives are outside this change.

**Roadmap alignment**

This extends existing chat connectors and secrets capabilities. Related
public work: #14037 and #13954 cover Slack MCP prerequisites and user
OAuth. No duplicate bot-registration PR was found.

## What Changed

- Share one reviewed manifest builder between automatic registration and
manual setup.
- Add replay-safe migration 0318 and company-bound registration state
with vault references and uncertain-creation recovery.
- Add registration, installation, callback, and resume APIs with
short-lived, single-use OAuth state.
- Save installation credentials before downstream checks and preserve
bot identity constraints.
- Reduce automatic setup to four screens. Keep advanced app details,
manual recovery, and existing-app setup.
- Upload the agent avatar with the Paperclip dark background. Link the
OAuth installer's account and send setup DMs.
- Show agent and connector-owner avatars. Simplify settings, access, and
conversation screens.
- Discover joined Slack channels and enable them by default. Start a
task from a bare mention and admit same-thread follow-ups.
- Refresh Slack tool guidance each turn. Add native-form, file,
approval, and delivery regressions plus manual model probe definitions
and sanitized acceptance records.
- Update deployment/database docs, OpenAPI, redaction, removal cleanup,
production Storybook stories, and provider browser tests.
- Merge current master and move the registration migration after its
latest migration without rewriting published commits.

The completed Slack success view intentionally has a single centered
**Done** action and no **Save & exit**, as explicitly requested by the
product owner. `DESIGN.md` records this exception; unfinished setup
steps retain the aligned wizard footer.

## Verification

- Passed after the master merge: repository typecheck, full build,
Storybook build, design-token gates, module-boundary gates, and
migration generation.
- Passed: all 352 focused Slack deterministic tests and all 14 affected
provider browser tests. Browser tests use controlled provider fixtures
and a separate throwaway instance.
- Passed on current head `c5d01e0e2`: the complete GitHub test matrix
(general server, chat, all workspaces, serialized server, and Runner),
all eight browser shards, typecheck/release registry, build, canary dry
run, security checks, and policy gates. There are 52 passing checks and
no pending or failing checks.
- Greptile completed on the exact current head with 5/5 and no
actionable findings or open review threads.
- Local repair verification passed 93 focused tests, including same-app
reinstall after revocation and rejection of consent started before
revocation, the AgentMail browser journey, and repository typecheck.
Local build and Storybook build also passed. The redundant local
full-suite rerun was stopped after the complete current-head CI matrix
passed.
- Real Slack setup and agent replies were exercised in the authorized
isolated test drive during the setup iteration.
- The ten additional model probes were attempted with legacy
`codex_local`, `gpt-5.6-sol`: five passed, two failed, and three were
partly verified. Native runtime is not qualified. See
`server/src/services/connectors/slack/evals/2026-10-08-acceptance.md`
for evidence and limits.
- Passing model probes cover native forms, downloaded file bytes, bare
mentions with thread replies, explicit posts/reactions, and saved
approval denial.
- The controlled uncertain-write probe found wrong delivery-check IDs.
The canvas fallback attempt used an invented tool name. Search
pagination/native search, a private-source denied-tool receipt, and
distinct board/webhook origins remain unqualified.

Reviewer path: enable Chat connectors, start Slack chat setup, select an
agent, enter an app-configuration access token, and approve Slack
installation. Send a message to the bot and confirm that setup advances
to success. Inspect settings and allowed channels. See
`doc/connections/SLACK-AUTOMATIC-SETUP.md` for deployment and recovery.

## Risks

- Slack app creation has no provider idempotency guarantee. A timeout
after dispatch stays uncertain until the operator checks Slack.
- OAuth needs a stable public HTTPS board origin. Webhook ingress may
use a separate configured HTTPS origin. Workspace policy can delay
installation.
- Migration 0318 can replay safely on instances that applied the earlier
development migration.
- OAuth installation now links the installer to the initiating Paperclip
user. Identity checks and company access rules still apply.
- Joined channels now enable bot responses by default. Linked-user
authorization and per-action approval rules still apply.
- Model behavior has the documented delivery-check and canvas fallback
failures. A passing CI run does not establish that every model probe
passed.
- Removing the connection does not delete the customer's Slack app. No
new first-party telemetry is added.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository tools, code
execution, and browser verification. The runtime does not expose a more
specific authoring model ID or context-window size. The live bot probes
used OpenAI `gpt-5.6-sol` through `codex_local` in legacy mode.

## 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-08 06:33:31 -05:00
DottaandPaperclip 6c1a75da49 feat(connections): make AgentMail a default connection with inline setup (#14772)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Connections give agents access to external services.
> - AgentMail needs both a saved key and an inbox assigned to the agent.
> - Chat requests offered a setup link instead of an inline card and
could treat a saved key as complete.
> - Inbox setup also hid address conflicts behind a generic server error
and a separate review step.
> - This pull request makes AgentMail a default connection, adds the
inline card, reduces setup to two steps, and shows conflicts beside the
address.
> - Shared native dropdown styles also give every caret a consistent
inset.

## Linked Issues or Issue Description

**What happened?**

AgentMail requests in chat did not show a usable inline connection card.
Manual setup required extra screens, ignored saved account keys, and
could trap new-address setup in a locked inbox dropdown. Agent selectors
omitted the avatar from the selected value. A taken address could
produce an HTTP 403 from AgentMail and appear as an internal server
error. Native dropdown arrows also touched the right edge of their
fields.

**Expected behavior**

Make AgentMail available as a default connection. Ask for the API key
inline, with a direct link to its provider page. Default human access to
the company and agent access to the requesting agent. Resume the agent
only after an assigned inbox is active. Manual setup should ask for an
agent and email address, then finish. Address checks should run as the
user types. Taken addresses should show clickable alternatives. A domain
dropdown beside the name should prefer a verified custom domain. Setup
should suggest authorized saved AgentMail keys and show agent avatars in
the picker and selected value.

**Steps to reproduce**

1. Ask an agent to connect AgentMail when it has no assigned inbox.
2. Check that an inline API-key card appears and links to the provider's
API-key page.
3. Open AgentMail setup, choose an agent, and request an address that is
already taken.
4. Correct the inline error, refresh, and finish setup with the same
request ID.
5. Inspect native dropdown carets in light, dark, disabled, and
right-to-left states.

Uses the bounded provider-error parser merged in #14768. Related work:
#13256 introduced AgentMail; #14725 expanded connection search.

## What Changed

- Stop recurring email queries for tasks that have no email thread.
Share the query between the thread provider and activity view. Keep
email-task updates and invalidation-based discovery.
- Make AgentMail available without the experimental chat setting. Keep
the catalog, setup and management routes, agent Channels tab, task email
feed, receiving worker, and agent tools available by default. Other
experimental chat providers stay gated.

- Make the email address and copy icon a single clickable action with
the shared Copied! confirmation. Add View inbox linking directly to the
matching AgentMail console inbox, with the address encoded as one URL
path segment.

- Reorganize inbox Settings around the copyable email address, usage
instructions, and receiving status. Move reconnect credentials into a
disclosure and separate the Disconnect action. Add production Settings
stories for active, paused, unassigned-address, revoked, webhook,
long-address, mobile, and reconnect states. Show repair controls when
the inbox has an error. Keep usage instructions tied to an active inbox
with an address.

- Add AgentMail channel intents and an inline key field with the direct
API-key URL.
- Keep setup and retry state tied to the interaction. Require an active
inbox for completion. Preserve company and agent access checks.
- Reduce manual setup to agent selection and email selection. Put the
domain dropdown beside the address and default to a verified custom
domain. Preserve explicit choices across reloads. Keep receiving
settings under Advanced options.
- Check the initial address and edits after a 350 ms pause. Abort
superseded requests and ignore stale responses. Show clickable
suggestions and retain known creation conflicts across reloads.
- Add a company-scoped, manager-only address check using the saved
credential. Search the visible inbox list instead of fetching an
uncreated inbox: live AgentMail retains negative lookups that can break
subsequent access-key creation. Unlisted addresses remain unknown;
creation is authoritative.
- Suggest labeled saved AgentMail keys in both manual setup and the
inline card. Filter by company, provider, active credential, and
current-user grants on the server. Prefer an account key and preserve
the selected key or an explicit new-key choice across refresh. Use
verified scope metadata and bounded concurrent checks for legacy keys.
Never return secret values.
- Catch an inbox-only key before the email step. Allow its existing
inbox only after an explicit choice. Recover old locked drafts at the
key picker. Save the replacement key before retiring an empty draft,
then use a new setup URL so refresh preserves the switched account; stop
if cleanup fails. Preserve already allocated addresses and their
original accounts.
- Use the shared AgentSelect in email setup. Show the canonical agent
avatar in each option and the selected value, including other consumers
of the shared component. Add regression coverage for legacy and current
Lucide agent-mention icon formats.
- Start each catalog Add connection with a fresh setup identity. Honor
Finish setup's exact draft/account/address instead of resuming an
unrelated browser draft. Return Cancel and Done to Connectors and Email
settings to the inbox. Group the task/thread explanation in a How it
Works card.
- Route AgentMail catalog removal through the email inbox control API,
including unfinished drafts. Refresh both the catalog and inbox views.
- Render each inbox management tab separately. Access uses the saved
account grants and agent controls; Conversations and Activity use the
shared persisted email feed. Activity lifecycle actions use the email
API. Reconnect returns to inbox Settings. Conversation failures show a
retry instead of a false empty state. Email delivery recovery stays in
the task.
- Map documented provider address conflicts to a field error. Preserve
actionable messages for other failures.
- Preserve non-secret draft fields across refresh, scoped to the
requested agent. Never save API keys in browser storage. Resume partial
inbox creation with the original agent, address, and request ID.
- Show an already-created address with explicit retry and new-address
recovery instead of locked inputs. Preserve the original inbox and
resumable draft when choosing another address. Distinguish runtime-key
404 errors and log safe provider status/operation/code.
- Apply final agent access once within email setup authorization for a
new account whose original installs are unchanged. Preserve later
permission edits and reused account installs. Support in-place retry of
progress loading.
- Let a failed inline setup change keys after retiring an empty draft.
Persist its replacement setup identity without storing secrets. Recover
a server-saved account when refresh interrupts the save response, while
preserving intentional account changes.
- Render the production setup in Storybook and add error, recovery, and
mobile states.
- Inset native select carets in shared CSS. Preserve custom icons,
listboxes, keyboard behavior, and forced-color controls.
- Add browser regression coverage and an AgentMail Product E2E case with
persisted-state and rendered-card evidence.

## Verification

- Full `pnpm -r typecheck`, `pnpm build`, `pnpm check:token-gates`, and
`git diff --check` passed after the default-availability change.
- All 485 focused tests passed. These cover setup, management, catalog
and route gates, connection intents, email authorization, Cursor
execution, and the OpenAPI contract. All 39 email integration tests run
with the experimental chat setting off.
- The shared polling change passed four behavioral tests, UI typecheck
and build, and token gates.
- `tests/e2e/agentmail.spec.ts` passed with the actual server setting
off. This full-stack browser test uses simulated provider responses. It
covers catalog entry, saved keys, editable address and domain controls,
creation, conflicts, retry, all management tabs, clipboard feedback, the
provider link, and task email rendering.
- In the live local browser, Add connection reached the editable email
step with the saved account key. The verified custom domain was selected
by default. Both domain choices worked. The existing inbox Settings page
remained available. Both active inboxes completed new mail checks with
the setting off. No new provider inbox or email message was created for
this pass.
- Earlier live provider acceptance covered creation on a verified custom
domain, Finish connecting on the reported draft, successful mail checks
after refresh, and catalog removal of disposable draft and active
connections. Clicking the email address copied the exact address and
showed Copied!. View inbox opened the same inbox in AgentMail’s console.
No email messages were sent.
- Production setup and Settings Storybook builds and interactions
passed. Settings states include active, paused, unassigned, revoked,
webhook, long-address, mobile, and reconnect. Receiving and
revoked-access stories had zero accessibility violations.
- Full local `pnpm test:run` on an earlier revision completed with
14,709 passing, 87 skipped, and four transient failures. All four failed
cases passed in focused reruns without product changes. That serial full
local command was not repeated after each follow-up. The latest-head
full CI suite is the final test gate.
- CI found an obsolete browser assertion that hid every channel when the
flag was off. Updated it to keep AgentMail and the Channels surface
visible while preserving the GitHub chat route gates. All 11 provider
browser tests passed locally after scoping the Channels selector to the
agent sidebar. Two initial local attempts stopped at temporary Postgres
initialization. The passing run used a separate disposable database on
the existing local Postgres server; it was removed after the test.
- Updated the remaining sidebar and aggregator discovery assertions for
default AgentMail availability. Ordinary task fixtures now return no
email thread. All 128 sidebar/task-page tests and all 42 aggregator
tests passed locally.
- Latest head `b42bb4cd5cc9f2d01a99ab8026832d5a956ea85f`: full CI
passed, with 54 successful checks including Snyk and two intentional
Storybook skips. The CI run is
https://github.com/paperclipai/paperclip/actions/runs/37020833647. A
fresh Greptile review scored 5/5 with no unresolved threads. Live model
evaluations and inbound/outbound email delivery were not run.

## Risks

- AgentMail no longer needs experimental opt-in. Setup still requires a
human to connect an account and assign an inbox. Inline setup creates an
inbox after a human submits a new or saved key. Company access, agent
access, inbox assignment, and completion checks remain enforced.
- AgentMail read APIs cannot prove global address availability. The
visible-list check is bounded to 100 entries and cannot see inboxes
outside the key’s scope. The UI reports this limitation, suggests
alternatives without claiming they are free, and keeps final creation
conflicts inline. Lookup outages show an error without preventing the
authoritative creation attempt.
- Native select CSS affects the whole app. Custom-icon selects and
multi-row lists are excluded. Forced-color mode keeps the browser caret.
- Saved-key discovery uses stored verified scope metadata and checks
authorized legacy credentials concurrently within a shared three-second
deadline. Provider outages mark legacy choices unavailable; users can
still enter another key. Final use rechecks authorization and provider
access.
- No database migration or transport default change. Live connection
remains the default.

## Model Used

OpenAI Codex, GPT-6, with reasoning, tool use, and code execution. The
exact served model ID and context-window size are not exposed in this
session.

## 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 (focused suites; full-suite
limitation documented above)
- [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 (latest head
`b42bb4cd5cc9f2d01a99ab8026832d5a956ea85f`)
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
(latest head `b42bb4cd5cc9f2d01a99ab8026832d5a956ea85f`)
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-02 10:01:15 -05:00
DottaandPaperclip d72389bee2 feat: add Browser Use Cloud connector and live task browsers (#14627)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The Apps gateway gives agents governed access to external tools.
> - Browser Use Cloud can run browser work, but a tool result alone does
not let a person watch or take over.
> - A task needs a durable browser session, a visible viewer, and
recorded costs.
> - This pull request adds a Browser Use Cloud v4 connection and
interactive browser tabs on tasks.
> - People can follow the work, interact with the page, and retain the
browser after the agent finishes.

## Linked Issues or Issue Description

**Problem or motivation**

Agents need governed access to Browser Use Cloud. People need to see and
interact with the same browser from the task. A browser must remain
available after a run finishes and appear at the correct point in the
task feed.

**Proposed solution**

Add a native REST connection for the v4 API. Bind each session to its
company, task, agent, and credential grant. Open its interactive viewer
in the task side panel. Record provider costs as financial events. Use
`browser-use-cloud` as the app and connector key. Keep its skill with
the connector and deliver it only with authorized connection tools.

**Alternatives considered**

A v3 MCP connection would expose tools without the v4 lifecycle
integration. An external viewer link would leave the task. A fixed
viewer size would prevent pages from responding to changes in the task
pane.

**Roadmap alignment**

This extends the governed Apps gateway and Connected Apps roadmap. It
uses the existing task, grant, secret, approval, and financial records.
The work was requested by the maintainer. A search found no duplicate
Browser Use connector PR or issue.

## What Changed

- Add the Browser Use Cloud app, brand asset, API-key connection, and
profile settings under the `browser-use-cloud` key.
- Bundle the `browser-use-cloud` skill with the connector. Keep it out
of global `skills/` discovery. Deliver it only with authorized task/run
connection tools. Remove retired connector skill keys from runtime
overlays and preserve unrelated browser skills.
- Expose seven v4 tools through the governed gateway and deliver them to
native and CLI agents.
- Persist sessions, browsers, runs, event and recovery cursors, shutdown
leases, and cumulative cost accounting. Recover uncertain paid starts
without replaying them.
- Enforce task ownership, credential grants, approvals, revoked access,
and budget limits.
- Add interactive task browser tabs and compact chronological feed
entries. Retain the viewer across tab switches and keep visible idle
browsers open.
- Add debounced automatic viewport fitting, standard size presets, and a
viewer ownership lease.
- Add lifecycle, authorization, accounting, viewport, UI, and Storybook
coverage.
- Add an idempotent database migration after the current master
migration. Preserve deployed migration hashes. Migrate pre-release Cloud
connection and financial keys without replacing grants, credentials, or
browser history.
- Document provider behavior, live acceptance results, and the lack of
documented passkey forwarding.

## Verification

- Full workspace typecheck and production build pass on the updated
branch.
- Token gates, brand asset validation, module boundaries, and migration
ordering pass.
- Cloud tests verify global skill exclusion, authorized task/run
delivery, unassigned agents, disabled connections, revocation, adapter
isolation, and secret exclusion. The existing AgentMail connector
assignment test also passes.
- Migration replay runs twice against existing browser work and
financial records. It preserves the records and avoids duplicate costs.
- The focused provider, app catalog, OpenAPI, connection gateway, and
migration regression suites pass. Recovery coverage includes lost
replies, process crashes, provider rejection, and browser arrival
acknowledgement.
- All 54 checks pass on `2974b5f03641ad0cea3c941d8c02579316fa8c92`,
including the full test matrix, browser E2E shards, build, typecheck,
security, and release canary. Two optional Storybook jobs are skipped.
- Greptile is 5/5 on the same commit, with zero unresolved review
threads. The corrected review uses the actual master-to-head diff.
- The local `pnpm test:run` started and was stopped after the full CI
matrix passed. It did not complete locally; the full-suite result above
comes from CI.
- Earlier live acceptance used an isolated company with a capped
provider credential. The agent opened paperclip.ing, the embedded viewer
accepted navigation, and the same browser stayed available after
completion and tab switches.
- The local Storybook build passes. Stories cover the panel, footer,
feed entries, settings, lifecycle failures, and viewport modes with an
offline viewer fixture.

## Risks

- Browser Use charges for hosted work. Provider caps and local budget
checks reduce exposure; reported costs can arrive after work completes.
- Viewer and CDP URLs grant access to the browser. The server validates
and restricts them. They are excluded from agent results and durable
event data.
- Runtime resizing of v4 agent browsers uses a provider option confirmed
by live testing but absent from its published agent schema. Resizing
during a click may invalidate coordinates. Fixed presets remain
available.
- Viewport ownership is process-local and resets on restart. The
lifecycle and accounting records remain in the database.
- The original intermittent embedded-viewer stall has not been fully
diagnosed. A bounded reconnect and active-session recovery cover the
observed failure paths.
- Live tests did not cover every revocation, approval, rate-limit, or
restart case. Deterministic integration tests cover those paths. Passkey
forwarding is not claimed.
- Unknown create outcomes keep the credential available for cleanup.
Run-list absence cannot prove a paid POST was rejected, so recovery
stays pending until it can identify provider work.

## Model Used

OpenAI Codex, GPT-6. Used reasoning, repository search, code execution,
browser interaction, and test tools. The exact serving model ID and
context-window size were not exposed in this session.

## 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-09-30 07:13:16 -05:00
DottaandPaperclip b0155a681a feat(slack): connect Paperclip conversations and scheduled messages (#13920)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Slack conversations use the same tasks and agents as the Paperclip
board.
> - A board reply must reach that Slack conversation and let the agent
continue the work.
> - An assigned agent also needs its Slack tools during normal tasks and
scheduled routines.
> - Both paths must keep the linked user's authority, delivery rules,
and conversation history.
> - This pull request adds those paths and reduces setup friction for
Slack bots.

## Linked Issues or Issue Description

**Subsystem affected**

Server orchestration, Slack connector tools, shared contracts, and chat
setup UI.

**Problem or motivation**

Replies entered in Paperclip did not provide a complete round trip to
the linked Slack thread. Slack and board wakeups could select different
model sessions for the same task. Agents also lacked their assigned
Slack tools outside Slack-origin work, which prevented a routine from
sending its responsible user a briefing. Inviting a bot could leave the
new channel disabled.

**Proposed solution**

Mirror human board messages with author attribution and route the agent
result to the same thread. Use the same session key across both entry
points. Supply Slack tools to the connection's assigned agent in normal
tasks and routines, using the current responsible user's verified link.
Enable newly invited channels while preserving explicit disabled
choices. Add a browser-agent setup prompt to the Slack wizard.

**Alternatives considered**

A separate Slack scheduler or task dispatcher would duplicate existing
Paperclip workflows. Reusing the connection owner's identity would grant
the wrong authority. Replaying old channel history could start
unintended work. This change uses ordinary task wakeups, routine
dispatch, and Slack's original invitation mention event instead.

**Roadmap alignment**

Extends the shipped Scheduled Routines and governed Apps capabilities.
It does not add a separate task lifecycle. Related work: #13828 and
#13809. Related test stabilization: #13877. The existing plugin
Slack-control proposals are separate from this built-in connector
change.

## What Changed

- Queue human Paperclip messages for the original Slack thread with
display-name attribution and stable delivery identities. Require the
author’s current linked Slack identity and recheck access before
delivering messages or agent replies.
- Apply pause, dependency, cancellation, and closed-workspace guards
before explicit Board sends request work and again when the durable
outbox dispatches it.
- Route agent results back to Slack and preserve model-session
continuity, including replies that reopen completed tasks.
- Resolve assigned Slack connections for normal agent tasks and
routines. Recheck the responsible user's link, membership, and
permissions at execution.
- Add `slack_open_dm` for the responsible user's bot DM and request the
`im:write` scope.
- Enable newly discovered invited channels. Keep explicit OFF choices
and normal admission and deduplication rules.
- Add a copyable Slack setup prompt for a computer-use agent, with
Storybook coverage. Share the prompt-button component with GitHub.
- Update Slack tool documentation and runtime instructions.
- Stabilize the mobile project browser test by waiting for the final
canonical route before editing, preserving all persistence assertions.

## Verification

- Live staging: invited the bot after the first mention. The channel
became enabled and the bot answered that original mention.
- Live staging: a normal Paperclip reply appeared in Slack with author
attribution. The agent completed the calculation and replied once in the
original thread and in Paperclip.
- Live staging: a codeword entered in Slack was recalled from Paperclip.
A following Slack calculation used the result from the Paperclip turn.
Run metadata confirmed the same model session for both entry points.
- Live staging: a scheduled routine used `slack_open_dm` and
`slack_post_message` to deliver one DM. The existing app was reinstalled
with `im:write`. The test routine was paused after verification.
- Before the master merge: 397 focused feature tests passed. The
continuity fix passed all 76 issue comment/update route tests and six
focused route/integration cases. Typecheck, build, and token gates
passed.
- Review fixes: 47 focused integration cases passed, covering link
revocation/replacement, private membership removal, guarded outbox
dispatch, concurrent workers, lost scheduler responses, a real
one-connection pool, exact reply provenance, and attachment retries. All
99 issue-comment route tests and the Slack catalog browser test passed.
- Full local typecheck, production build, token gates, and
module-boundary checks passed. The full local test command passed 25,915
tests before a 15-second timeout in
`issue-thread-interaction-routes.test.ts`; that entire suite passed on
isolated rerun (81 tests). Remaining serialized coverage is provided by
the current-head CI shards.
- An unchanged Cursor adapter test hit its 10-second limit in CI; all
five tests in that file passed on a local rerun in 3.11 seconds, and the
failed CI shard passed on its single retry.
- The preview-server readiness test passed a local rerun (28 tests). The
mobile-project readiness fix passed three repetitions of both browser
tests (6/6).
- Final commit `64ac0d9897f4353375996f1b1b38e5040bdeb0a0`: all CI gates
passed, including all eight browser shards, all server/chat suites,
typecheck, build, runner checks, and security checks. Greptile reviewed
this exact commit at 5/5; all review threads are resolved.

## Risks

- Human messages on a Slack-linked task now publish to its Slack thread.
The task banner states this behavior. Incoming Slack messages and
internal agent bookkeeping must not echo back.
- Normal tasks and routines can now use the assigned bot. Authority
remains bound to the current responsible user's link; it does not fall
back to the connection owner. Revocation, private-context limits, and
queued-write checks still apply.
- Existing Slack apps need `im:write` and a reinstall to open DMs. Other
existing capabilities remain available without that scope.
- New invited channels default to enabled. Explicit disabled choices
remain disabled. Channels created by bot tools still require a person to
enable responses.
- No database migration or new provider credentials are required.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, code execution, GitHub CLI,
and browser tools. The runtime does not expose a more specific model
build identifier 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-09-24 10:51:45 -05:00
DottaandPaperclip a10702a878 feat(slack): add governed tools for Slack-origin tasks (#13828)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat connectors let people start and continue agent tasks from other
services.
> - A Slack conversation needs access to its surrounding discussion and
Slack collaboration tools.
> - The agent must use the linked requester's access and keep private
material within its permitted audience.
> - This pull request adds Slack tools through the existing connector
contribution and approval framework.
> - People can ask an invited bot to read a discussion, create follow-up
tasks, and collaborate in Slack.

## Linked Issues or Issue Description

**Subsystem affected**

Chat connectors, connector runtime, tool gateway, and connection
Settings/Access.

**Problem or motivation**

Slack-origin tasks can receive messages but cannot inspect the rest of a
channel or act through the originating bot. People must paste context or
configure a separate integration.

**Proposed solution**

Supply typed Slack tools and a bundled skill only to the originating
task and assigned agent. Resolve the linked requester on the server.
Check bot and requester access before reads and writes. Use existing
durable actions and approvals. Retrieved messages remain source
material.

**Alternatives considered**

Slack's user-OAuth MCP server does not replace the customer-created chat
bot. An unrestricted Web API proxy would not provide suitable permission
or publication boundaries.

**Roadmap alignment**

This extends the existing MCP Tool Gateway & Apps work with a provider
contribution. It does not add a task dispatcher or a separate Slack task
lifecycle. Related: #11144 covers generic per-user MCP grant execution;
this change binds Slack bot operations to chat-origin tasks.

## What Changed

- Add 39 typed Slack tools, a method/scope matrix, a bundled skill, and
shared native/HTTP execution.
- Bind tools to company, endpoint, task, run, assigned agent, and
admitted linked requester. Check membership and revocation on each call
and before queued writes.
- Add paginated reads, bounded history search, source links, messages,
file uploads, reactions, pins, bookmarks, topics, canvases, lists, and
approved channel operations.
- Restrict private-source publication, including automatic replies and
uploaded deliverables. Keep other people's bot DMs inaccessible.
- Reuse action receipts, idempotency, approvals, and reconciliation.
Suppress an identical explicit-send/final-reply duplicate. Return
governed results through their verified originating conversation.
- Add endpoint-bound personal search OAuth storage and lifecycle. Keep
native real-time search disabled until a runtime meets Slack's
transient-result requirements. Current runtimes use bounded history
search.
- Show capabilities, scope upgrades, and personal search authorization
in Settings/Access and Storybook. Document provider and runtime limits.

## Verification

- Current head `0eb21cba4`: CI checks pass and Greptile is 5/5 with no
unresolved findings. One unchanged rapid-callback timing test passed on
a single CI retry.
- Approval presentation regressions cover board-comment precedence and
exact Slack publication; the expanded database assertion passed in CI.
The local PostgreSQL startup probe later became unavailable, so that
final assertion was verified in CI. Slack setup and failed-run retry
browser tests also passed locally.

- Full workspace typecheck and build passed. Server typecheck/build
passed again after the approval routing fix.
- Broad local suites passed in separate groups: server 12,958 tests, UI
6,555, shared 770, skills catalog 20, and other workspace packages
2,652. CLI and serialized server checks passed after environment/timeout
retries. These are composite results, not one uninterrupted green
full-suite invocation.
- PostgreSQL authority regression covers admitted identity,
cross-company/task/agent rejection, recovery, retained-session
revocation, OAuth refresh/disconnect races, approval execution, exact
publication lineage, retries, uncertain sends, and duplicate
suppression.
- Gateway/response regressions cover separate-origin approval batches
and durable continuation. Focused provider, access, search, native
runtime, route, and AgentMail regressions pass.
- Storybook capability, missing-scope, OAuth configuration,
authorization, and disconnect states were inspected in the browser.
- Live staging: read a channel decision and full thread, create exactly
two assigned backlog tasks, add a reaction, paginate discovery to
exhaustion, and return bounded search matches with source links and
coverage.
- Live staging: create/edit/read a canvas and list, inspect the canvas
in Slack, post/edit one message, and create a channel only after
approval. New channels remain disabled for responses.
- Live staging: read a response-disabled channel from the requester's
DM; writes to that channel were denied. The test setting was restored.
- Final live retest passed: explicit file upload and exact content
read-back; approved deletion of only the disposable bot message;
continuation confirmation returned to the original Slack thread without
repeating the action.
- Optional OAuth, private multi-user boundaries, native RTS, and CLI
provider execution are not fully live-qualified. The staging agent
initially supplied malformed tool arguments; valid arguments succeeded,
and the tool/skill descriptions now emphasize UUID write keys.

## Risks

- Existing Slack apps must add scopes and reinstall for new
capabilities. Provider plans and document permissions can still restrict
operations.
- Instances need an independent `PAPERCLIP_TOOL_ACTION_SIGNING_SECRET`
for governed tool actions. The staging instance was configured with
explicit operator approval; fleet provisioning is a separate gap.
- Native RTS is not exposed on current transcript-retaining runtimes.
Bounded history scans are deliberately reported as incomplete. Inline
file reads support text/canvas content up to 256 KiB; other types return
metadata.
- Private document edits fail closed when the full audience cannot be
verified. Uncertain effects other than posts/uploads require inspection
instead of blind retries.
- Shared approval-delivery code now separates outcomes by source run to
preserve origin boundaries. No database migration is required.
- A separate completion-validator gap remains when the agent cites a
prior run's registered artifact during finalization. It asked for
registration again even though Slack delivery was confirmed. This change
does not add a connector-specific task-completion policy.

## Model Used

OpenAI GPT-6 through Codex, with repository tools, code execution, and
browser testing. The exact deployed model identifier and context-window
size were not exposed in the session.

## 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-09-22 15:29:07 -05:00
DottaandPaperclip 2083bf6f9a feat(connections): add AgentMail inboxes and email tasks (#13256)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Connections give agents controlled access to external services.
> - Experimental channels already map conversations to tasks and durable
work queues.
> - Email needs inbox ownership, recipient envelopes, delivery records,
and explicit sends.
> - This pull request adds AgentMail to that infrastructure and keeps
the provider key in the server vault.
> - Agents can receive and send email from local or sandbox execution
while the board follows each conversation in its task.

## Linked Issues or Issue Description

**Problem or motivation**

Agents need dedicated email addresses. Incoming email should become
assigned work. Internal task comments and progress must never become
outgoing email by accident.

**Proposed solution**

Add experimental AgentMail connections, an inbox assignment wizard,
durable email intake and publication, task email cards, and
authenticated API, CLI, and native runtime actions. Agents use Paperclip
credentials to request sends. Paperclip owns the provider key and
enforces access and task authority.

**Alternatives considered**

A general mailbox MCP connector does not provide durable task binding or
publication boundaries. A separate mailbox application duplicates task
collaboration. The board instead directs the agent through the normal
task conversation.

**Roadmap alignment**

This extends the existing experimental connections and task
infrastructure. Product scope and interaction design were reviewed with
the maintainer. Related connection authority work: #11831 and #11818.
The duplicate search found no competing task-based AgentMail
integration.

## What Changed

- Add AgentMail catalog data, shared contracts, company-scoped email
records, and an additive migration.
- Add vaulted setup, inbox assignment, access grants, trust guidance,
and provider-side allowlist guidance.
- Support WebSocket and signed-webhook intake through a shared durable
pipeline, deduplication, catch-up, and task wakeups.
- Queue explicit new conversations and replies with immutable send
intents, idempotency, delivery state, and uncertain-send resolution.
- Show inbound and outbound email cards in normal task conversations.
Keep internal messages internal.
- Add task-scoped CLI actions and the sandbox callback routes required
for Daytona execution.
- Provide a dedicated AgentMail skill automatically only to agents with
active authorized inbox assignments. Keep email instructions out of the
universal Paperclip skill.
- Advertise connector-owned `agentmail_inboxes`,
`agentmail_read_thread`, `agentmail_send`, and `agentmail_delivery`
tools only in eligible native sessions. Recheck live authority on
execution.
- Isolate Codex CLI connector skills by agent and skill revision.
Deliver the assigned skill in the run prompt for adapters that use
shared skill directories, including resumed turns. Keep automatic skills
out of manual persistent sync. Show them as read-only and document the
pattern in the connector playbook.
- Fix AgentMail health checks that entered local-stdio validation and
optional missing Codex credential cleanup in sandboxes.
- Add API, pipeline, authorization, sandbox, browser, and Storybook
coverage.

## Verification

- Live AgentMail testing covered WebSocket intake, signed webhooks,
restart catch-up, and a full receive → task → Daytona Codex CLI →
explicit reply → Delivered round trip. The reply was verified in the
other inbox. The normal task composer also initiated an outgoing email
child task.
- The connector-skill change was verified in the browser: AgentMail
appears once as an automatic, read-only skill with its assigned address.
Disabling experimental chat connections removes it; re-enabling restores
it. A regression test covers assignment data arriving after library
data.
- Connector regression coverage passed 178 runtime utility, email
integration, skill-route, and heartbeat tests. All 17 Codex execution
tests passed, including per-agent skill isolation, model identity,
revision changes, removal, and prompt delivery without shared skill
files.
- After rebasing onto master, all 44 focused email, heartbeat, and
native-authority tests passed. All 313 native-session executor tests
passed. The UI regression suite passed all 3 tests. These test sets
overlap earlier focused runs.
- Full workspace typecheck and build passed after the rebase. Token
gates passed. Earlier focused Playwright task/setup coverage and the
Storybook build also passed.
- Native connector tool execution uses deterministic integration tests.
Live Daytona qualification used the Codex CLI adapter; the new
shared-home prompt fallback has deterministic coverage.
- The full repository suite is run by CI. The earlier unsharded local
full-suite attempt was stopped after the equivalent CI suites passed and
is not reported as a completed local run. Greptile reviewed
`7e57dc267a8446d3c906e3cc5b8abc94fb8860eb` at 5/5 with no unresolved
threads. All server, workspace, serialized server, and browser suites
passed in CI. The build job hit a five-second timeout in a runner
transport test; both variants and the full 80-test file passed locally
with unchanged timeouts. The build passed on retry on the same commit
without code or timeout changes. All required CI gates, including the
final `ci / verify` and `ci / e2e` summaries, are green on
`7e57dc267a8446d3c906e3cc5b8abc94fb8860eb`.

## Risks

- Email from external senders can start normal agent work. Setup
recommends a low-trust agent and AgentMail sender controls. Sender
addresses never grant board membership.
- Provider timeouts can leave uncertain sends. Retries retain their
idempotency key; expired windows require reconciliation or operator
resolution.
- Connector skills and native tools are assignment-dependent and require
current access. Revocation denies retained calls; assignment changes
select a new runtime context.
- Activation remains behind the experimental-channel setting. The native
runner path has deterministic coverage; live Daytona qualification used
the Codex CLI adapter.
- Schema changes are additive. Inbox ownership is unique across
companies. Disconnect preserves provider inboxes and task history.

## Model Used

OpenAI GPT-6 (Codex). Used reasoning, repository tools, code execution,
and browser testing. The exact deployment model ID and context-window
size were not exposed in this session.

## 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-09-11 16:56:38 -05:00