@kentcdodds/onepassword
Resolve 1Password Connect item fields for secret-aware fetch with website host allowlisting.
README.md
98 lines · 5.2 KB · Markdown@kentcdodds/onepassword
Intent
Bind 1Password Connect as a Kody custom secret provider so agents can use
{{secret/1password:…}} placeholders in secret-aware fetch without ever
seeing vault values. Resolve item fields over Connect, allowlist hosts from the
item's websites or URL fields, and keep grants on item-id refs (UUID or
26-char Connect ids).
Optionally deploy the official Connect Server (connect-api + connect-sync)
to Fly.io via ./connect/deploy-fly.
Setup
- Run a 1Password Connect Server (or deploy with this package — see Connect on Fly below) and mint a Connect token with read access to the vaults you need.
- Save the Connect token as the user-scoped secret
ONEPASSWORD_CONNECT_TOKEN(never paste the token into chat): configure ONEPASSWORD_CONNECT_TOKEN. After you know your Connect hostname, edit the secret and add that host toallowedHostsif needed. - Turn on Custom secret providers for your account (feature flag) from Custom secret providers.
- Bind this package on
Secret providers (or
secretProviderBind) with:- provider:
1password - door secret:
ONEPASSWORD_CONNECT_TOKEN - config:
{"connectHost":"https://kody-onepassword-connect.fly.dev"}(or your Connect host)
- provider:
- Prefer item-id refs so grants work without a vault round-trip:
{{secret/1password:i/<item-id>/password}}— Connect item ids are usually 26-char lowercase alphanumeric (not UUIDs); UUIDs are still accepted.
Connect on Fly
Default app: kody-onepassword-connect →
https://kody-onepassword-connect.fly.dev
- From 1Password Developer → Connect servers, download
1password-credentials.json, Base64-encode it, and save as ONEPASSWORD_CONNECT_OP_SESSION (Base64 of the file — not raw JSON). Approve hostsapi.machines.devandapi.fly.ioon that secret. - Ensure
flyApiTokenexists with the same Fly API hosts approved (update hosts if needed). - Deploy:
import deploy from 'kody:@kentcdodds/onepassword/connect/deploy-fly'
const result = await deploy()
// => { ok: true, appName, url, region, bind, ... } // no secret values- Smoke
GET /heartbeat, thenGET /v1/vaultswith the Connect Bearer token. - Bind with
config: { connectHost: 'https://kody-onepassword-connect.fly.dev' }.
Why Base64 in the secret? Fly Machines config.files.raw_value expects
Base64 file bytes. deploy-fly expands {{secret:ONEPASSWORD_CONNECT_OP_SESSION}}
into that field, writes /home/opuser/.op/1password-credentials.json, and sets
container env OP_SESSION to that path (official Connect semantics). Kody only
expands placeholders inside secret-aware fetch, so the secret must already be
Base64. Do not set a Fly app secret named OP_SESSION to Base64 — that overrides
the path. Do not use raw ONEPASSWORD_CONNECT_CREDENTIALS_JSON as the file bytes
secret.
Exports: ./connect, ./connect/source, ./connect/deployment-guide,
./connect/deploy-fly.
Placeholder grammar
| Form | Notes |
|---|---|
{{secret/1password:i/<item-id>/<field>}} | Preferred. Canonical grant key. Item id: UUID or 26-char Connect id (^[\da-z]{26}$). |
{{secret/1password:op://Vault/<item-id>/<field>}} | Synonym when the item segment is already an id. |
Name-based op://Vault/Item/password | Not locked/granted until you switch to an item-id segment. |
Field matching (in order): field id, field label (case-insensitive), then
purpose shortcuts password → PASSWORD, username → USERNAME,
notes → NOTES.
Host allowlist (fail closed if empty): hostnames from item.urls[].href
websites, plus fields typed/labeled as URL (Secure Notes often have an empty
websites list but a URL field — point that field at the fetch host, e.g.
https://discord.com).
Done when
- Connect is reachable at your
connectHost(Fly deploy optional). secretProviderBindsucceeds with this package and your Connect host config.- An ad hoc secret-aware
fetchto an allowlisted host resolves{{secret/1password:i/<item-id>/password}}. - Saved packages that need the ref have an Allow grant from
secretProviderLock.
See AGENTS.md for agent notes.