Skip to content

Changelog

Source: en/reference/changelog.md · Live: https://docs.1pass.dev/en/reference/changelog LLM-sanitized: internal links absolutized, VitePress containers → admonitions, line numbers in the Jump-to Index reference this rendered file (1-indexed).

📍 Jump-to Index

  • L32-L40: ## 2026-07-08 — SDK Swift v1.1.0 — device PAK exchange, refresh verification, revoke/disconnect primitives
  • L41-L49: ## 2026-07-02 — SDK v1.0.1 security hardening (at_hash + JWKS kty)
  • L50-L61: ## 2026-06-24 — Passkey Phase 1–3
  • L62-L88: ## 2026-05-28 — RP registration hurdles (Phase 2–5e) + Agent Quickstart
    • L66-L71: ### Docs / agent surface
    • L72-L81: ### RP registration hurdles (server-side, autoDeploy=off, manual deploy)
    • L82-L84: ### Migration
    • L85-L88: ### Tests
  • L89-L121: ## 2026-05-15
    • L100-L110: ### 2026-05-11 — Added target_session_token PoP
    • L111-L121: ### 2026-05-11 — canonical resolution applied to the Easy Bracket RP
  • L122-L151: ## 2026-04-27 — Security review wave (Phase 1-14)
    • L127-L130: ### Critical
    • L131-L138: ### High
    • L139-L144: ### Medium
    • L145-L151: ### Summary of SDK user impact
  • L152-L168: ## v0.1-alpha (2026-04-22 sync)
  • L169-L175: ## Known limitations
  • L176-L182: ## Roadmap (β)

Changelog

2026-07-08 — SDK Swift v1.1.0 — device PAK exchange, refresh verification, revoke/disconnect primitives

The Swift SDK now absorbs three backend auth calls that RPs used to hand-roll. All changes are additive (existing symbol signatures unchanged) — existing v1.0.x integrations keep working with no code change, and the new surface is opt-in.

  • LogiAuth.verify(_:) — verifies the id_token from LogiAuthStorage.refresh()'s LogiAuthResult using the same JWKS cache and RS256 verification as signIn(), promoting it to a verified LogiSession. Trusting a refreshed token's sub/email without verification reopens, on the refresh path, the signature gap that signIn closes — always route cold-launch session restore through verify. (A refresh response carries no nonce, so nonce is not checked; at_hash is present-only.)
  • LogiDeviceKey (LogiAuthStorage module, actor) — exchanges the OAuth JWT for a device-bound PAK (logi_pak_...) via POST /api/v1/me/device_keys/exchange. The /api/v1/* endpoints require a PAK, not the JWT, so RPs that need this exchange now use the SDK instead of a hand-rolled copy. It persists device_uuid/device_secret idempotently to the Keychain and coalesces concurrent calls. When migrating an existing install, inject the legacy keychainService to preserve the stored credential (otherwise the server mints a fresh orphan DeviceCredential, with the 10/h exchange rate-limit and 409 device_claimed_by_other_user risk).
  • LogiAuthStorage.revokeRefreshToken() / disconnectApp(pak:) — backchannel primitives. revokeRefreshToken() invalidates the stored refresh_token server-side (RFC 7009; a public client sends client_id only; best-effort). disconnectApp(pak:) disconnects the RP via DELETE /api/v1/me/connected_apps/{client_id} (Bearer=PAK, profile:write) and returns true only on 2xx or 404, false on 401/403/5xx/timeout — so the caller can preserve local credentials and retry (preserving account deletion's "server success → local wipe" invariant). signOut() remains a local-only wipe; its contract is unchanged.
  • Integration guide: iOS (Swift). SPM from: "1.1.0", tag v1.1.0. All existing v1.0.1 golden vectors pass (non-breaking).

2026-07-02 — SDK v1.0.1 security hardening (at_hash + JWKS kty)

Non-breaking security hardening applied across all 7 SDKs (swift · android · browser · node · flutter · ruby · python).

  • at_hash binding — the id_token's at_hash claim (base64url_nopad(SHA256(access_token UTF-8 bytes)[first 16 bytes]), OIDC §3.1.3.6) is verified against the access_token (present-only). Code-exchange SDKs wire the access_token internally to confirm the access_token↔id_token binding before returning the session; standalone verification can pass it via an accessToken argument. Rejected with at_hash_mismatch.
  • JWKS kty filter — signing-key selection now filters kty=="RSA" + use∈{null,sig} + alg∈{null,RS256} before the kid match, so an EC (or other) key mixed into the JWKS still resolves the correct RSA signing key — robust to future key-type expansion. See the JWKS reference.
  • Swift — fail-closed CSPRNG (SecRandomCopyBytes) + duplicate OAuth callback parameter guard. Android — re-verify the rotated id_token before persisting on refresh.
  • Published: npm @logi-auth/browser@1.0.1 · @logi-auth/server@1.0.1, gem logi_auth 1.0.1, pub.dev logi_auth 1.0.1, SPM · JitPack v1.0.1 tags. All existing v1.0.0 golden vectors still pass (non-breaking).

2026-06-24 — Passkey Phase 1–3

Server behavior for passkey login and approval flows that external RPs need to understand.

  • WebAuthn L3 metadata storage — stores backup_eligible, backup_state, backup_state_changed_at, and aaguid per passkey. RPs can inspect sync eligibility and AAGUID through passkeys:read responses.
  • sign_count anomaly WORM audit — when the authenticator counter goes backward, authentication is not failed solely for that signal, but an append-only audit event is written to AuthenticationAuditLog.
  • Web Conditional UI login — adds a passkey login path based on /api/v1/passkeys/authentication_options and /api/v1/passkeys/authenticate. When the user selects a passkey in the browser Conditional UI, logi creates the web session.
  • App-approval passkey step-up — users with approval_mode=passkey approve push approval requests with a UV-bearing passkey assertion. The challenge is bound to the PushApprovalRequest to prevent reuse.
  • Unauthenticated passkey rate limits — documents the unauthenticated limits that RPs adding their own passkey login UI need to know. POST /api/v1/passkeys/authentication_options is capped at 20/min/IP, and POST /api/v1/passkeys/authenticate is capped at 15/min/IP + 30/min/credential. See Rate Limits for the exact values.
  • Last-passkey deletion lockout prevention — blocks deleting the last active passkey while passkey-only approval mode is enabled, so the user does not lose their approval path.
  • Authenticate hardening / throttle parity — prevents malformed credential JSON from surfacing as a 500, and aligns the per-credential throttle with JSON body parse/rewind handling.

2026-05-28 — RP registration hurdles (Phase 2–5e) + Agent Quickstart

Prevents AI agents from mass-producing RPs (Relying Parties) through automation, plus a docs cleanup around a single entry point.

Docs / agent surface

  • New Agent Quickstart/guide/agent-quickstart (Korean, 308 lines) + .en (English mirror). An 8-step execution order + automatic track detection + the F1–F8 pitfalls + a self-verify checklist. The ## ⭐ Agents start here section at the top of llms.txt exposes this page as the single entry point.
  • Webhook signature templatestemplates/webhook (rails.rb / express.ts / nextjs-route.ts). Dual signature format + 5-minute replay window + timing-safe compare are baked in. Blocks the // TODO: verify signature anti-pattern.
  • "📋 Copy for LLM" button — top-right of every docs page. Copies the current page's .md mirror to the clipboard + a 2-second toast. Localized, dark-mode-aware, and mobile-friendly.
  • @1pass/mcp v0.2.0 — adds 3 read-only docs tools (fetch_quickstart / get_doc / list_docs). No auth required. Fetch logi docs in natural language from Claude Desktop, Cursor, and Codex.

RP registration hurdles (server-side, autoDeploy=off, manual deploy)

  • identity_verified_level gate — an unverified developer is blocked from registering an RP. The JSON response includes verify_url. The console page shows a permanent banner + an "✉️ Send verification email" CTA (Phase 5c).
  • created_via channel recordingweb | cli | mcp | api | rake. Self-identified via the X-Logi-Client-Type header. Permanently recorded in the audit log.
  • Automated risk assessment (creation_risk_flags jsonb)wildcard_redirect_uri / sensitive_scope / unlisted_scope / high_volume_developer (≥5 in 7 days) / new_developer_account (within 7 days of signup) / suspicious_app_name (placeholder regex). These flags are evaluated at registration time and permanently recorded in the database.
  • Race-safe high-volume countCurrent.user.with_lock { evaluate + save } serializes concurrent registrations. Even with 5 firing at once, exactly 1 passes.
  • Rack::Attack throttle — POST /developer/applications at 10/h + 30/d per developer session. POST /api/v1/applications has the same cap per PAK token (blocking CLI/MCP/automated mass production). Applied alongside the global api/ip 60/min for defense in depth.
  • High-risk approval ack gate — when wildcard_redirect_uri or sensitive_scope appears alone, or 2+ flags accumulate, an admin can't approve without an explicit risk_acknowledged: true. The web console replaces the button with "⚠ Approve despite known risk," and a Turbo confirm dialog shows the flag list. The iOS admin API (/api/v1/admin/applications/:id/approve) returns HTTP 409 risk_acknowledgement_required when it's missing. ApplicationSubmission#approve! + auto_approve_during_beta share the same gate.
  • AdminAlertMailer high-risk alert — when creation_risk_flags is non-empty, the mailer runs deliver_later. A 30-minute per-developer cooldown (Rails.cache) + a rescue on enqueue failure. Recipients are configured via the RP_HIGH_RISK_ALERT_TO env (operator-only).
  • Stronger admin queue UI — each app row shows a risk badge + the created_via label. A "⚠ Has risk signals" quick filter. At the top, a risk-statistics card for the last 7 days (total new / containing risk signals / ack-pending counts + the top-5 flag distribution).

Migration

  • 20260528130250_add_creation_audit_to_oauth_applicationsoauth_applications.created_via (string, default web) + creation_risk_flags (jsonb, default []) + a partial index on jsonb_array_length(creation_risk_flags) > 0.

Tests

  • Model/request/mailer combined: 102+ examples PASS (Phase 2–5e integration regression).
  • 6 rounds of Codex review (Phase 2 / 3 / 4 / 5a / 5b / 5b-followup) — every BLOCK resolved.

2026-05-15

  • LogiAuth Swift SDK 0.1.2 — added redirect_uri scheme/host/path verification to handleCallback (ainote 2026-05-15 incident fix)
  • @logi-auth/browser@0.1.0 released on npm — a zero-deps PKCE SDK for SPAs
  • Expanded OIDC Discovery docsresponse_modes_supported, ui_locales_supported, service_documentation, revocation_endpoint_auth_methods_supported (basic/post; none excluded), claims_parameter_supported / request_parameter_supported / request_uri_parameter_supported / require_request_uri_registration (explicitly false)
  • /diagnose endpoint restored — added the missing DiagnoseController + view (RP self-diagnosis)
  • docs.1pass.dev track split — added /tracks/{mobile,web,api}, introduced a line-numbered jump index in llms.txt
  • Bidirectional Cross-Host Handoff API added (PR #28-32) + global logout
  • Console SSO Phase 3 (start.1pass.dev) + desktop Web SSO Phase 1+2 introduced (Mac Safari Universal Link bouncer)
  • multi-role join table introduced — role separation per host (Phase 1)

2026-05-11 — Added target_session_token PoP

Added a new credential path so a user who holds both account sessions on the same device can merge accounts without the OTP email round-trip.

  • New endpoint POST /api/v1/me/merge/session-token — issues a 5-minute-TTL token from the target session
  • The existing POST /api/v1/me/merge accepts either target_session_token or otp_code
  • Providing both credentials at once yields 422 conflicting_credentials
  • Audit log marker: merged_via=session_token (distinct from OTP's merged_via=otp)

For the full flow, see the session-token PoP guide.

2026-05-11 — canonical resolution applied to the Easy Bracket RP

Easy Bracket (RP, https://easy-bracket-lookbook.onrender.com) applied canonical_user_ids resolution — which reflects logi account merges — to its production environment. The ENFORCE_CANONICAL_RESOLUTION=true flip is complete (currently 0 merged users — it will start working automatically from the first future merge).

  • Every Pundit policy checks ownership against user.canonical_user_ids
  • ActionCable / background jobs / the PttChannel model are canonicalized
  • Push-notification fanout deduplicates canonical ids
  • Device tokens / API tokens are invalidated immediately on a user.merged webhook

Other RPs can integrate the same pattern. See the RP Integration Guide.

2026-04-27 — Security review wave (Phase 1-14)

A batch of hardening based on a full-codebase security review. For the detailed items, see docs/todo/security-review-findings-2026-04-27.md.

Critical

  • P0-1 Device bootstrap re-authenticationdevice_secret_digest + dual-mode (bootstrap → secret revealed once, refresh → digest verification). Blocks re-issuing a PAK for an existing anonymous account using only its device_uuid.
  • P0-2 Identity reporter capabilityidentity_verification_reporter flag + identity_verification_methods allowlist. Resolves the issue where an arbitrary OAuth app could change a trust level.

High

  • Rate limiting — 8 rack-attack throttles (across login/oauth/devices/identity/otp/passkeys/api)
  • Webhook SSRF — both registration and dispatch do DNS verification, blocking private/link-local/multicast addresses (IPv4+IPv6). To defend against DNS rebinding, connect directly to the verified IP.
  • Webhook secret redesign — store webhook_secret_plaintext with ActiveRecord encryption. When the BCrypt fallback is used, add an X-Logi-Secret-Deprecated header + Deprecation (RFC 9745).
  • Passkey UV policy — introduced purpose=step_up → enforces user_verification: required. otp_verified_at is set only based on whether UV actually happened (authenticator_data.user_verified?).
  • OAuth authorize return — when not logged in, save request.fullpath to return_to_after_authenticating → preserves state/scope/redirect_uri/code_challenge.
  • Session fixation — call reset_session on successful login (preserve only the necessary keys, then re-store them).

Medium

  • New identity:level scope — the behavior where identity_verified_level was automatically included in profile is deprecated. New apps must explicitly request identity:level. Existing apps stay compatible via legacy_identity_claim=true (a 6-month migration period).
  • CSP report-only enableddefault-src 'self', frame-ancestors 'none', /csp-violation-report sink. The switch to enforce comes after analyzing violation logs.
  • CORS — dynamic verification of oauth_applications.allowed_origins. The wildcard + credentials combination is not used.
  • Secret expiration policyclient_secret_expires_at / webhook_secret_expires_at with a 1-year TTL + an audit log alert 30 days before. Issuing a token with an expired client_secret yields invalid_client.

Summary of SDK user impact

  • ⚠️ EncryptedSharedPreferences (androidx.security:security-crypto 1.1.0) is deprecated — don't use it in new SDKs. Prefer DataStore + Tink or Ackee Guardian.
  • ⚠️ Specifying the iOS Keychain option is required: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly (without the suffix, it syncs to iCloud Keychain).
  • ⚠️ On flutter_secure_storage 10.0+, you must set up Android backup exclusion (backup_rules.xml) yourself.
  • ⚠️ The webhook receiving side must handle the X-Logi-Secret-Deprecated: true header + a rotation notice.
  • New mobile guides: iOS, Android, Flutter, React Native.

v0.1-alpha (2026-04-22 sync)

Completed milestones (see GitHub tags):

  • m0-bootstrap — Rails 8 scaffold, Cloudflare/Render checklist
  • m1-auth — basic auth (role + device_uuid + lockout)
  • m2-oauth-core — OAuth 2.0 + PKCE S256 + JWKS + Refresh rotation
  • m3-developer-portal — Developer Portal + Admin (iOS 26 Liquid Glass)
  • m4-consent — consent screen + consent records
  • m5-cli — Personal API Keys + the logi CLI (Ruby/Thor)
  • m7-otp — TOTP 2FA + backup codes + a sensitive-operation gate
  • m8-m10-security-observability — Passkey + Login Logs + Webhooks
  • m12-m13 — Suspicious Detection + Admin Audit
  • m6-ios-scaffold / m6-m11-ios-mcp — iOS app + MCP server
  • m14-docs — VitePress + Scalar docs site + OpenAPI 3.1
  • m15-android-scaffold / m15-complete — Android app + Play Integrity round-trip + Sentry
  • 2026-04-22/oauth/revoke (RFC 7009), /oauth/introspect (RFC 7662), a recurring job to purge sign-in history after 90 days

Known limitations

  • Production deployment to Render / Cloudflare / GitHub Pages is not complete yet
  • Push notifications (APNs/FCM) not implemented
  • Play Integrity production decode and ANDROID_APP_CERT_SHA256 injection not yet complete
  • The iOS associated domain migration to api.1pass.dev is complete (v0.4, 2026-04-22)

Roadmap (β)

  • β1: dynamic scope + required marking (in progress)
  • β2: custom claims (User#custom_claims implemented)
  • β3: sign-in history alerts + APNs/FCM
  • β5: mobile production hardening (Play Integrity decode, cert fingerprint, associated domain cleanup)

최종 수정:

Identity가 제품의 신뢰를 만듭니다.