1Password

1Password Connect over the REST API. Pure net/http, no third-party SDK.

Schemeop://
Modulegithub.com/xavidop/mamori/providers/onepassword
Sensitiveyes
Watchpoll
AuthOP_CONNECT_HOST, OP_CONNECT_TOKEN

Install

go get github.com/xavidop/mamori/providers/onepassword
import _ "github.com/xavidop/mamori/providers/onepassword"

Using the ref

An op:// ref points at one field of one item in a 1Password vault. This matches the familiar 1Password secret-reference format.

op://<vault>/<item>/<field>
PartRequiredWhat it means
<vault>yesVault name or id. A name is looked up first, then falls back to being treated as an id.
<item>yesItem title or id within that vault.
<field>yesField label or id on that item.

Examples

  • op://Production/postgres/password reads the password field of the postgres item in the Production vault.
  • op://Production/stripe/api_key reads the api_key field of the stripe item.
type Config struct {
	DBPassword secret.String `source:"op://Production/postgres/password"`
	APIKey     secret.String `source:"op://Production/stripe/api_key"`
}

Values are marked Sensitive, and Value.Version is the item version (or a content hash when the item has no version).

Explicit configuration

import opprov "github.com/xavidop/mamori/providers/onepassword"

mamori.WithProvider(opprov.New(
	opprov.WithHost("https://connect.internal:8080"),
	opprov.WithToken(os.Getenv("OP_CONNECT_TOKEN")),
))

Close() is idempotent and terminal: after it returns, every Resolve reports errors.Is(err, mamori.ErrUnavailable) locally, without contacting Connect. It also returns its own idle HTTP connections to the pool, and leaves connections belonging to the rest of your process alone. A client injected with WithHTTPClient is never closed, so it stays usable for whatever else holds it.

Watch

1Password Connect has no push channel, so mamori polls (WithPollInterval + jitter).

Error classification

HTTP statusmamori kind
404not_found
403permission_denied
401unauthenticated
429rate_limited
5xxunavailable
400invalid
anything elseunknown

Connect’s error responses carry only a numeric status and a free-text message, no machine-readable error code, so classification is by status alone. A missing vault, item, or field is reported directly as not_found with its own message rather than through this table.

Verified by unit tests and the conformance kit against an in-process HTTP fake of the Connect API (injected *http.Client). Live behavior against a running Connect server is covered by //go:build integration tests.