v2: 1Password credential provider (org + personal service accounts, reference credentials) - #163
v2: 1Password credential provider (org + personal service accounts, reference credentials)#163yourbuddyconner wants to merge 14 commits into
Conversation
…dential resolver Wires the Task 1 OnePasswordService into EngineHost.buildCredentialResolver: rows carrying metadata.onepassword now resolve through the service instead of a raw store read, while every other row stays byte-identical. Threads onePassword through providers/node.ts and the integration test harness.
Add live-gated SDK e2e test (OP_SERVICE_ACCOUNT_TOKEN, skip-clean without it) and a Deviations section documenting SDK version, the metadata.onepassword smuggle-bypass fix, and web helper/hook changes found during the implementation pass.
…erences Align scope=org browsing with the org token's intended trust model: any authed org member can browse once the token is connected (org-owned credential rows and settings stay admin-only). Also reject onepassword references on the github service, since the session resolver's github branch ignores them silently.
…ion path Session.credentialProvider() reads user-owned rows only — the spec's assumed owner read-union never existed, so admin-created org-wide reference credentials were dead rows. buildCredentialResolver now falls back to the org row on a user-owner miss, reference rows only; plain org rows stay session-invisible. Pinned by 3 tests.
|
Post-PR adversarial review found a gap all prior review layers missed: org-scoped reference credentials were dead rows on the session path. The engine's Fixed in ef154cc: |
…d the org-row fallback
…olution across session/workflow/channel readers
…; reconcile spec note
Credentials can now be stored as 1Password secret references (
op://vault/item/field) instead of raw secrets. The reference rides an ordinary credential row's metadata; the secret is resolved at read time via the 1Password SDK using an org-level or personal service-account token, and is never persisted.Design:
docs/specs/2026-07-21-onepassword-credentials-design.md(incl. Deviations) · Plan:docs/plans/2026-07-21-onepassword-credentials.mdWhat's in here
packages/api/src/services/onepassword.ts— the only@1password/sdk(^0.4.0) import point: client cache, 5-min resolve cache, token lookup (reserved serviceonepassword, org- or user-owned), typedOnePasswordAuthError.services/credential-resolution.ts): credential reads follow user row → org row precedence for ALL credential kinds, with 1Password reference resolution built into the read — one shared helper consumed by the session resolver, the workflow action invoker, and ChannelHost. Reservedonepasswordrows (the tokens themselves) are excluded from the read path entirely.EngineHost.buildCredentialResolver— zeropackages/enginechanges; errors surface as tool errors, never session failures./api/onepassword/*— vault/item/field picker backend + org settings (personal-token toggleallowPersonalOnePassword, default on for single-user mode)./api/credentialsextension — reference creation with save-time resolve validation;metadata.onepasswordis a reserved key (smuggle-guarded);githubreferences are rejected (github keeps its own user→org token-service tiering).Trust model & deliberate behavior changes (documented in-code and in-spec)
Disclosures
OP_SERVICE_ACCOUNT_TOKEN=… [OP_TEST_REFERENCE=…] pnpm --filter @valet/api test -- src/integration/onepassword.live. The suite is verified skip-clean for CI.llm-providers.e2e(expired real OpenAI key fixture in the local env).Tests
Every task passed an adversarial per-task review, a whole-branch final review, and a post-PR adversarial pass that caught and fixed a real gap (org-scoped rows were dead on the session path — no owner read-union existed; now resolved by the owner-precedence contract). Battery at HEAD:
pnpm typecheckclean · api 1460+ passed · web 447 · engine 430 (zero engine diff vs merge-base).