Files
PaperClipAI/maps/agent-access-map/connection-setup.md
T
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

317 lines
14 KiB
Markdown

# Connection setup — agent access
Product map: [Connection setup](../feature-map/connection-setup.md).
Feature ID: `connection-setup`.
Review date: 2026-10-12. Source commit: `f981fa3cc10cb8663a87dec60345fbff46d54d0a`.
This is a source-reviewed baseline of representative operations and known gaps.
Each capability needs operation-level review before its entire scope can be
qualified. No live agent execution is claimed. Follow the [map contract](../README.md)
for format, permission checks, evidence and maintenance.
Prompt Injection Prevention reuses shared OpenRouter API-key setup directly from
Settings → Connections. It adds no Apps provider or transport. Credential ownership
and audience rules are the existing connection rules; saving a connection alone
does not activate the service. See [service configuration](../../doc/prompt-injection-prevention.md).
1Password adds a service-account catalog method. Agents request access through
the existing connection tools and invoke its reviewed item actions through the
run-scoped gateway. The service-account token stays in the selected user/company
vault; vault boundaries are enforced by 1Password. Setup remains board-owned.
Evidence and limits: [1Password connector](../../doc/connections/1PASSWORD.md).
## `catalog`
Capability ID: `connection-setup/catalog`.
Review: `baseline`.
API: `present` — representative operation IDs:
- `POST /runtime-tools/connections/search`.
Agent access: `available` — Native connections_search / run-bound runtime-tools MCP.
Policy: Setup and credentials belong to the addressed authorized human; active-run tools
can search/request access.
Evidence: `source-only` —
[implementation](../../server/src/routes/connection-intents.ts#L130) at the reviewed
commit above.
Verification: `not-run` — exercise a listed permitted operation with actual agent
credentials/run context; inspect its result and applicable persistence/attribution.
Assert the relevant denied actor, owner, company or mode from Policy. Review the
remaining operations before qualifying the whole capability.
Gaps: Runtime tool broker searches available services without granting connection
administration.
Notebook is internally gated by `enablePaperclipNotebook` (default off, no settings toggle). Disabled instances hide setup/discovery and deny curated Notebook dispatch and publishing; local removal and grant revocation remain available.
The connector catalog declares the feature key. Shared availability checks use
the saved application identity. Notebook owns publication and file uploads;
Paperclip uses its existing MCP tools and OAuth flow.
Notebook source addition: `paperclip-notebook` is discoverable through
`connections_search` and requestable through `connection_request`. Its standard
personal authorization requests read, write, share, and delete scopes. Notebook
page ownership remains enforced by the remote service; a client-supplied agent
label grants no authority. The direct MCP connection requires no Cloud instance
enrollment. Notebook fixture evidence: `verified` against disposable PostgreSQL 18
with controlled MCP responses — [Notebook integration](../../doc/connections/PAPERCLIP-NOTEBOOK.md)
and [generic OAuth fixture](../../server/src/__tests__/generic-mcp-connection.test.ts).
Ordinary MCP calls retain assignment and Allowed / Ask first / Off policy.
Live deployed publication and hosted/self-hosted OAuth remain release checks.
## `identity-and-access`
Capability ID: `connection-setup/identity-and-access`.
Review: `baseline`.
API: `present` — representative operation IDs:
- `POST /api/companies/{companyId}/tools/connections`.
Agent access: `restricted` — Board setup API plus agent connection_request.
Policy: Setup and credentials belong to the addressed authorized human; active-run tools
can search/request access.
Evidence: `source-only` —
[implementation](../../server/src/routes/connection-intents.ts#L130) at the reviewed
commit above.
Verification: `not-run` — assert the documented agent denial with an owned test fixture;
verify any listed agent request/result path separately. A delegated operation needs its
own policy and access review.
Gaps: Selecting account ownership/eligible agents is management; an agent can request
the intended connection.
## `credentials`
Capability ID: `connection-setup/credentials`.
Review: `baseline`.
API: `present` — representative operation IDs:
- `POST /api/agents/me/connections/{connectionId}/start-authorization`.
Agent access: `partial` — Scoped start-authorization/request flow; human provider login.
Policy: Setup and credentials belong to the addressed authorized human; active-run tools
can search/request access.
Evidence: `source-only` —
[implementation](../../server/src/routes/connection-intents.ts#L130) at the reviewed
commit above.
Verification: `not-run` — exercise a listed permitted operation with actual agent
credentials/run context; inspect its result and applicable persistence/attribution.
Assert the relevant denied actor, owner, company or mode from Policy. Review the
remaining operations before qualifying the whole capability.
Gaps: An initiation endpoint exists; it is not authorization to complete the person's
credential flow.
Braintrust uses the existing setup/request path for US and EU OAuth and API-key
methods. OAuth requests only `mcp`; provider authorization follows the selected
account's permissions. Personal invocation credentials must belong to their
user, while shared identities use company credentials. Region and explicit
method survive resume and reconnect. Agents use assigned tools through the
run-scoped gateway and receive no Braintrust token. See
[Braintrust](../../doc/connections/BRAINTRUST.md) for method keys and the
qualification matrix. Separate live US OAuth proof passed browser authorization,
49-tool discovery, bounded read, synthetic dataset insert/readback through actual
process-agent runs and gateway sessions, catalog refresh, OAuth reconnect, local
removal, post-removal denial, and structural API/log redaction. US API-key and
both EU methods remain `not-run` against real accounts. Live token expiry/refresh,
remote OAuth revocation, and native CLI automatic capability delivery remain
unqualified. Public metadata probes performed no registration or account
authorization; fixtures do not establish live proof for the remaining methods.
Daytona native setup uses an organization API key in the selected personal or
company vault grant. It does not borrow sandbox-provider credentials or CLI
login tokens. Agents use assigned provider tools through the normal run-bound
gateway; they cannot export the key. [Database-backed fixtures](../../server/src/__tests__/daytona-connection.test.ts)
cover selected vault ownership and gateway reads/writes with provider responses
replaced by fixtures. Real provider authentication remains unqualified.
Unikraft native setup uses an organization API token in the selected personal or
company vault grant. It does not borrow `unikraft login` state or `UKC_TOKEN`.
Agents use assigned provider tools through the run-bound gateway, limited to the
published metro hosts, and cannot export the token. [Database-backed fixtures](../../server/src/__tests__/unikraft-connection.test.ts)
cover vault ownership and gateway reads, writes and sandbox commands with
fixture provider responses. Real provider authentication remains unqualified.
## `handoff`
Capability ID: `connection-setup/handoff`.
Review: `baseline`.
API: `present` — representative operation IDs:
- `POST /api/connection-intents/{interactionId}/complete`.
Agent access: `restricted` — Addressed-user completion; server wakes the agent with
updated access.
Policy: Setup and credentials belong to the addressed authorized human; active-run tools
can search/request access.
Evidence: `source-only` —
[implementation](../../server/src/routes/connection-intents.ts#L130) at the reviewed
commit above.
Verification: `not-run` — assert the documented agent denial with an owned test fixture;
verify any listed agent request/result path separately. A delegated operation needs its
own policy and access review.
Gaps: OAuth/callback and addressed-user checks are deliberate separate boundaries.
## `draft-recovery`
Capability ID: `connection-setup/draft-recovery`.
Review: `baseline`.
API: `present` — representative operation IDs:
- `POST /api/connection-intents/{interactionId}/phase`.
- `POST /api/tool-connections/{connectionId}/reconnect`.
Agent access: `restricted` — Human setup/resume APIs; agent request state and
continuation.
Policy: Setup and credentials belong to the addressed authorized human; active-run tools
can search/request access.
Evidence: `source-only` —
[implementation](../../server/src/routes/connection-intents.ts#L130) at the reviewed
commit above.
Verification: `not-run` — assert the documented agent denial with an owned test fixture;
verify any listed agent request/result path separately. A delegated operation needs its
own policy and access review.
Gaps: Board setup recovery exists. Browser-only navigation state is not automatically an
agent API gap.
## `task-request`
Capability ID: `connection-setup/task-request`.
Review: `baseline`.
API: `present` — representative operation IDs:
- `POST /runtime-tools/connections/request`.
Agent access: `available` — Native connection_request / run-bound runtime-tools MCP.
Policy: Setup and credentials belong to the addressed authorized human; active-run tools
can search/request access.
Evidence: `source-only` —
[implementation](../../server/src/routes/connection-intents.ts#L130) at the reviewed
commit above.
Verification: `not-run` — exercise a listed permitted operation with actual agent
credentials/run context; inspect its result and applicable persistence/attribution.
Assert the relevant denied actor, owner, company or mode from Policy. Review the
remaining operations before qualifying the whole capability.
Gaps: This is the existing agent bridge for human-required setup; do not invent a second
approval system.
## `channel-setup`
Capability ID: `connection-setup/channel-setup`.
Review: `baseline`.
API: `present` — representative operation IDs:
- `POST /api/companies/{companyId}/chat-endpoints`.
Agent access: `restricted` — Board channel management; agent requests required setup.
Policy: Setup and credentials belong to the addressed authorized human; active-run tools
can search/request access.
Evidence: `source-only` —
[implementation](../../server/src/routes/connection-intents.ts#L130) at the reviewed
commit above.
Verification: `not-run` — assert the documented agent denial with an owned test fixture;
verify any listed agent request/result path separately. A delegated operation needs its
own policy and access review.
Gaps: Provider endpoint, represented agent and linked sender are operator choices today.
Internal recovery: Telegram discovery walks bounded pages at startup. Configuration
commits only queue the changed connection; durable maintenance rows supply retry deadlines. Inactive subscription
repair is parked until an endpoint or connection change. This creates no agent
management permission or new API. Local database-backed provider-fixture tests in
[channel integration](../../server/src/__tests__/chat-channels.integration.test.ts)
cover recovery, rollback, retries and idle query silence; they do not establish
live provider or agent access.
## `failure`
Capability ID: `connection-setup/failure`.
Review: `baseline`.
API: `present` — representative operation IDs:
- `POST /api/tool-connections/{connectionId}/health-check`.
Agent access: `partial` — Agent observes connection tool errors; board repair APIs.
Policy: Setup and credentials belong to the addressed authorized human; active-run tools
can search/request access.
Evidence: `source-only` —
[implementation](../../server/src/routes/connection-intents.ts#L130) at the reviewed
commit above.
Verification: `not-run` — exercise a listed permitted operation with actual agent
credentials/run context; inspect its result and applicable persistence/attribution.
Assert the relevant denied actor, owner, company or mode from Policy. Review the
remaining operations before qualifying the whole capability.
Gaps: Error reporting and human repair exist; no generic agent permission to reconnect
accounts.
Supabase and Vercel deployment methods (2026-10-22) reuse human-authorized setup
and assigned run-scoped tools. Native Supabase calls use the saved project;
native Vercel calls use the saved team and validate project ownership. Tokens
remain in the selected personal/company vault grant and cannot be exported by
`mintConnectionTokenForAgent`. Action policies, changed-schema quarantine,
responsible-user access and immediate removal apply to deployment/configuration
calls. Database/provider-fixture evidence lives in
[deployment connector governance](../../server/src/__tests__/deployment-connections.test.ts).
It does not establish authenticated provider deployment, OAuth consent or remote
revocation. See [Supabase](../../doc/connections/SUPABASE.md) and
[Vercel](../../doc/connections/vercel.md) for the remaining live-proof matrix.
Native delivery (2026-10-23): reviewed REST connections are admitted in connection
readiness, native runtime snapshots, and runtime gateway preparation. The real
Codex walkthrough initially failed at all three despite a successful board test;
the database-backed lifecycle regression now covers ready search/request,
existing-card completion, assigned-tool search/call, and inactive/unrecognized
connection denial for both providers. After repair, a real Codex agent deployed
and configured both services. Supabase's Dashboard invocation returned the marker,
and Vercel's signed-in browser served the preview. The Vercel first-deployment
production exception remains recorded as a separate failed outcome; default
preview now requires an existing deployment and reports target mismatches for
reconciliation. See the provider documents for the external-deletion race limit.