Skip to content

fix(onepassword): validate integration against API docs, add file downloads#5365

Merged
waleedlatif1 merged 5 commits into
stagingfrom
worktree-1password-validate
Jul 2, 2026
Merged

fix(onepassword): validate integration against API docs, add file downloads#5365
waleedlatif1 merged 5 commits into
stagingfrom
worktree-1password-validate

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Added onepassword_get_item_file tool + route to download file attachments on 1Password items (Service Account SDK items.files.read / Connect files/{id}/content), and exposed attachment metadata (files) on get/create/replace/update item outputs so a file's ID is discoverable
  • Fixed update_item in Service Account mode: JSON Patch paths were resolved as literal array indices instead of 1Password's documented field-ID addressing (/fields/{fieldId}/...), so field edits silently no-op'd
  • Fixed the filter param in Service Account mode to honor SCIM eq exact-match semantics instead of always doing a substring match
  • Expanded the Create Item category dropdown from 9 to 19 real, creatable 1Password categories (was missing Software License, Email Account, Membership, Passport, Reward Program, Driver License, Bank Account, Medical Record, Outdoor License, Wireless Router, Social Security Number)
  • Replaced the block's single opaque response: json output with typed, per-operation output fields, matching repo convention
  • Removed incorrect password-masking on the Vault ID field (it's not a secret)
  • Re-exported tool types from the onepassword tools barrel

Type of Change

  • Bug fix
  • New feature (file download tool)

Testing

  • bun run type-check — clean
  • bunx biome check — clean
  • bun run check:api-validation:strict — passes
  • bunx vitest run app/api/tools/onepassword/utils.test.ts — 18/18 passing
  • Cross-checked every tool's request/response shape against the live 1Password SDK type definitions and the Connect API reference docs

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…nloads

- add onepassword_get_item_file tool + route for downloading item file
  attachments (SDK items.files.read / Connect files/{id}/content), backed
  by newly-exposed item.files metadata on get/create/replace/update item
- fix update_item JSON Patch applying array indices instead of 1Password's
  documented field-ID addressing (/fields/{fieldId}/...), which silently
  dropped field edits in Service Account mode
- fix Service Account mode's list-vaults/list-items filter to honor SCIM
  `eq` exact-match semantics instead of always substring-matching
- expand the create-item category dropdown from 9 to 19 real, creatable
  1Password categories (was missing SOFTWARE_LICENSE, EMAIL_ACCOUNT,
  MEMBERSHIP, PASSPORT, REWARD_PROGRAM, DRIVER_LICENSE, BANK_ACCOUNT,
  MEDICAL_RECORD, OUTDOOR_LICENSE, WIRELESS_ROUTER, SOCIAL_SECURITY_NUMBER)
- replace the block's single opaque `response: json` output with typed,
  per-operation output fields matching repo convention
- remove incorrect password-masking on the Vault ID field (not a secret)
- re-export tool types from the onepassword barrel
@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 2, 2026 4:52pm

Request Review

@cursor

cursor Bot commented Jul 2, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches secret/item write paths and returns base64 file payloads from vaults; fixes reduce silent no-ops on updates but incorrect patch handling could still corrupt items.

Overview
Adds Get Item File end-to-end (API route, contract, tool, block operation) so workflows can download item attachments via Service Account SDK or Connect; item responses now include a files metadata array to discover file IDs.

Service Account fixes: update_item applies JSON Patch on the Connect-normalized item shape, resolves /fields/{id}/... paths by field ID (not numeric index), then writes via shared connectItemToSdkItem. replace_item uses the same converter instead of inline SDK mapping. List vaults/items filtering uses matchesFilter for SCIM eq semantics instead of substring-only matching.

Block/UI: Per-operation typed outputs replace the generic response blob (legacy field kept empty for compatibility); Create Item gains 10 more categories; vault ID is no longer password-masked; Connect URL/token hidden for resolve_secret; filter field is advanced with wand help.

Connect proxy: connectRequest exposes headers and arrayBuffer() for binary file downloads.

Reviewed by Cursor Bugbot for commit e78839e. Configure here.

Comment thread apps/sim/app/api/tools/onepassword/utils.ts Outdated
@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a new onepassword_get_item_file tool and route for downloading file attachments from 1Password items, fixes the Service Account update_item bug where JSON Patch segments were resolved as numeric array indices instead of field IDs, corrects the SCIM eq filter to compare against the correct attribute, expands the category dropdown from 9 to 19 real 1Password categories, and replaces the block's single opaque response output with typed per-operation outputs.

  • File download (get-item-file/route.ts, get_item_file.ts): new route handles both Service Account (via client.items.files.read) and Connect (two-step metadata + content fetch) modes; document-category items are correctly resolved through findItemFileAttributes.
  • update_item Service Account fix (update-item/route.ts): patch ops are now applied to the normalized Connect-shaped item, then converted back to SDK vocabulary via connectItemToSdkItem before put() — eliminating the silent no-op that came from patching raw SDK fields with Connect paths.
  • connectItemToSdkItem helper (utils.ts): centralises Connect→SDK conversion for both replace and update routes, preserving SDK-only field metadata (e.g., password-generation details) via spread before explicit overrides.

Confidence Score: 5/5

Safe to merge; the core bug fixes are well-reasoned, the new file-download route is correctly gated behind auth, and both Connect and Service Account modes are covered.

All three bug fixes (PATCH field addressing, SCIM eq filter, category list) are validated by tests and cross-checked against API docs. The new connectItemToSdkItem helper correctly preserves SDK-only field metadata via spread. Two minor observations — null coercion via || vs ?? on field values, and a silent no-op when add targets a non-existent array element by ID — do not affect correctness for any documented 1Password PATCH usage pattern.

apps/sim/app/api/tools/onepassword/utils.ts (connectItemToSdkItem field value coercion) and apps/sim/app/api/tools/onepassword/update-item/route.ts (applyPatch add-at-specific-id silent drop).

Important Files Changed

Filename Overview
apps/sim/app/api/tools/onepassword/get-item-file/route.ts New route for downloading file attachments; handles both Service Account (SDK) and Connect modes correctly, including document-category items via findItemFileAttributes.
apps/sim/app/api/tools/onepassword/utils.ts Adds connectItemToSdkItem, findItemFileAttributes, and matchesFilter; minor: value: f.value
apps/sim/app/api/tools/onepassword/update-item/route.ts Fixes Service Account PATCH by applying ops to the normalized Connect-shaped item before converting back to SDK format; ID-based arrayIndexForSegment correctly replaces numeric index traversal.
apps/sim/blocks/blocks/onepassword.ts Replaces single opaque response output with per-operation typed outputs; adds get_item_file to operations; correctly extends category list to 19 categories; removes incorrect password masking from Vault ID.
apps/sim/tools/onepassword/get_item_file.ts New tool definition for file downloads; correct visibility settings (user-only for credentials, user-or-llm for IDs); transformResponse handles error case properly.
apps/sim/lib/api/contracts/tools/onepassword.ts Adds Zod contract for get-item-file route; correctly extends the get-item body schema with fileId validation.
apps/sim/tools/onepassword/utils.ts Adds files to transformFullItem output and FULL_ITEM_OUTPUTS schema; state description corrected from 'ARCHIVED or DELETED' to 'ARCHIVED, or absent/null when active'.
apps/sim/app/api/tools/onepassword/replace-item/route.ts Simplified by delegating field/section/website conversion to the shared connectItemToSdkItem helper; no behavior change for Connect mode.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Client
    participant GetItemFileRoute
    participant OnePasswordSDK
    participant ConnectServer

    Client->>GetItemFileRoute: POST /api/tools/onepassword/get-item-file
    GetItemFileRoute->>GetItemFileRoute: checkInternalAuth + parseRequest

    alt Service Account mode
        GetItemFileRoute->>OnePasswordSDK: client.items.get(vaultId, itemId)
        OnePasswordSDK-->>GetItemFileRoute: Item (with files[] / document)
        GetItemFileRoute->>GetItemFileRoute: findItemFileAttributes(item, fileId)
        alt file found
            GetItemFileRoute->>OnePasswordSDK: client.items.files.read(vaultId, itemId, attr)
            OnePasswordSDK-->>GetItemFileRoute: binary content
            GetItemFileRoute-->>Client: "{ file: { name, mimeType, data: base64, size } }"
        else not found
            GetItemFileRoute-->>Client: 404 File not found
        end
    else Connect mode
        GetItemFileRoute->>ConnectServer: "GET /v1/vaults/{v}/items/{i}/files/{f}"
        ConnectServer-->>GetItemFileRoute: "file metadata { name, size }"
        GetItemFileRoute->>ConnectServer: "GET /v1/vaults/{v}/items/{i}/files/{f}/content"
        ConnectServer-->>GetItemFileRoute: binary response (content-type header)
        GetItemFileRoute-->>Client: "{ file: { name, mimeType, data: base64, size } }"
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Client
    participant GetItemFileRoute
    participant OnePasswordSDK
    participant ConnectServer

    Client->>GetItemFileRoute: POST /api/tools/onepassword/get-item-file
    GetItemFileRoute->>GetItemFileRoute: checkInternalAuth + parseRequest

    alt Service Account mode
        GetItemFileRoute->>OnePasswordSDK: client.items.get(vaultId, itemId)
        OnePasswordSDK-->>GetItemFileRoute: Item (with files[] / document)
        GetItemFileRoute->>GetItemFileRoute: findItemFileAttributes(item, fileId)
        alt file found
            GetItemFileRoute->>OnePasswordSDK: client.items.files.read(vaultId, itemId, attr)
            OnePasswordSDK-->>GetItemFileRoute: binary content
            GetItemFileRoute-->>Client: "{ file: { name, mimeType, data: base64, size } }"
        else not found
            GetItemFileRoute-->>Client: 404 File not found
        end
    else Connect mode
        GetItemFileRoute->>ConnectServer: "GET /v1/vaults/{v}/items/{i}/files/{f}"
        ConnectServer-->>GetItemFileRoute: "file metadata { name, size }"
        GetItemFileRoute->>ConnectServer: "GET /v1/vaults/{v}/items/{i}/files/{f}/content"
        ConnectServer-->>GetItemFileRoute: binary response (content-type header)
        GetItemFileRoute-->>Client: "{ file: { name, mimeType, data: base64, size } }"
    end
Loading

Reviews (4): Last reviewed commit: "fix(onepassword): preserve field metadat..." | Re-trigger Greptile

Comment thread apps/sim/app/api/tools/onepassword/utils.ts
matchesFilter always compared against name/title regardless of the
attribute named in the eq expression, so `id eq "..."` incorrectly
matched against the display name instead of the id.
…audit

- restore a deprecated no-op 'response' output so pre-existing saved
  workflows referencing it fail soft (empty) instead of hard-erroring
  now that per-operation outputs replace it
- add missing block outputs (urls, favorite, version, state,
  lastEditedBy) for get/create/replace/update item so all real
  FULL_ITEM fields are discoverable as <Block.field> references
- hide Connect Server credential fields for Resolve Secret (Service
  Account only) instead of leaving them selectable and silently ignored
- correct two doc-string enum lists that advertised values the API
  doesn't return (vault type TRANSFER, item state DELETED)
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 5a1d535. Configure here.

…t mode)

update_item applied user JSON Patch ops (documented/typed against the
Connect-shaped vocabulary get_item returns: label/type/section.id)
directly onto the raw SDK item, whose vocabulary differs (title/
fieldType/sectionId, and SDK category enum strings vs Connect's
SCREAMING_SNAKE_CASE). Most patches beyond /title, /tags/-, and
/fields/{id}/value silently no-opped or could corrupt the item while
still reporting success.

Extracted the Connect->SDK item conversion already used by replace_item
into a shared connectItemToSdkItem helper. update_item now normalizes
the fetched item to Connect shape, applies patches to that, then
converts back before calling items.put() -- matching create/replace's
existing translation pattern.

Found via an adversarial final-verification pass that traced concrete
patch operations by hand against the SDK's actual field vocabulary.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/app/api/tools/onepassword/utils.ts Outdated
Comment thread apps/sim/app/api/tools/onepassword/utils.ts
connectItemToSdkItem rebuilt every field as a bare object, dropping
SDK-only metadata (e.g. password-generation details) that a raw
patch/replace previously left untouched. Now merges onto the existing
SDK field by id before applying the translated properties, and only
starts fields bare when they're genuinely new.

Also restored the || (not ??) fallback on title to match replace_item's
prior behavior of treating an explicitly empty title as "not provided".
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit e78839e. Configure here.

@waleedlatif1 waleedlatif1 merged commit 59d6b8a into staging Jul 2, 2026
16 checks passed
@waleedlatif1 waleedlatif1 deleted the worktree-1password-validate branch July 2, 2026 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant