| 127 | } |
| 128 | |
| 129 | async resolve(ref: string): Promise<string | undefined> { |
| 130 | if (!ref.startsWith(OP_REF_PREFIX)) { |
| 131 | // Redact the value — if someone accidentally stored a raw API key |
| 132 | // as an op reference, logging it would leak the credential. |
| 133 | log.warn("Invalid 1Password reference (not an op:// URI)", { |
| 134 | ref: `[redacted, length=${ref.length}]`, |
| 135 | }); |
| 136 | return undefined; |
| 137 | } |
| 138 | |
| 139 | const cached = this.cache.get(ref); |
| 140 | const now = Date.now(); |
| 141 | if (cached && cached.expiresAt > now) { |
| 142 | return cached.value; |
| 143 | } |
| 144 | if (cached) { |
| 145 | this.cache.delete(ref); |
| 146 | } |
| 147 | |
| 148 | // Decode percent-encoded segments for backward compatibility — |
| 149 | // earlier versions of buildReference used encodeURIComponent, but |
| 150 | // the 1Password SDK only accepts raw characters in op:// references. |
| 151 | let decodedRef: string; |
| 152 | try { |
| 153 | decodedRef = decodeURIComponent(ref); |
| 154 | } catch { |
| 155 | decodedRef = ref; |
| 156 | } |
| 157 | |
| 158 | const resolveWithClient = async (): Promise<string | undefined> => { |
| 159 | const client = await this.getClient(); |
| 160 | const value = await withTimeout( |
| 161 | client.secrets.resolve(decodedRef), |
| 162 | RESOLVE_TIMEOUT_MS, |
| 163 | `1Password resolution timed out after ${RESOLVE_TIMEOUT_MS}ms for ${ref}` |
| 164 | ); |
| 165 | if (typeof value !== "string") { |
| 166 | log.warn("[OnePasswordService] Resolved secret was not a string", { |
| 167 | ref, |
| 168 | type: typeof value, |
| 169 | }); |
| 170 | return undefined; |
| 171 | } |
| 172 | |
| 173 | this.cache.set(ref, { |
| 174 | value, |
| 175 | expiresAt: Date.now() + CACHE_TTL_MS, |
| 176 | }); |
| 177 | return value; |
| 178 | }; |
| 179 | |
| 180 | try { |
| 181 | return await resolveWithClient(); |
| 182 | } catch (error) { |
| 183 | if (error instanceof DesktopSessionExpiredError) { |
| 184 | this.client = null; |
| 185 | this.initPromise = null; |
| 186 | |