@oh-my-pi/pi-ai 18.1.21 → 18.1.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.1.22] - 2026-09-14
6
+
7
+ ### Fixed
8
+
9
+ - 400-request debug dumps now redact provider-specific auth headers (`x-goog-api-key`, `x-amz-security-token`, and any header whose name carries a key/token/secret), not just a fixed allow-list, so a shared dump can no longer leak a live API key ([#12007](https://github.com/can1357/oh-my-pi/issues/12007)).
10
+
5
11
  ## [18.1.20] - 2026-09-13
6
12
 
7
13
  ### Fixed
@@ -60,6 +60,8 @@ export interface ProviderDefinition {
60
60
  readonly envKeys?: KeyResolver;
61
61
  /** Provider transport can authenticate without a resolved API-key string. */
62
62
  readonly allowsMissingApiKey?: boolean;
63
+ /** APIs whose provider transport resolves credentials without a stored account. */
64
+ readonly nativeAuthApis?: readonly string[];
63
65
  /** Provider-owned model normalization that must run before API-specific option mapping. */
64
66
  readonly prepareModel?: ProviderModelPreparer;
65
67
  /** Provider-owned request shaping applied before generic API dispatch. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oh-my-pi/pi-ai",
3
- "version": "18.1.21",
3
+ "version": "18.1.22",
4
4
  "description": "Unified LLM API with automatic model discovery and provider configuration",
5
5
  "keywords": [
6
6
  "ai",
@@ -124,11 +124,11 @@
124
124
  "fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
125
125
  },
126
126
  "dependencies": {
127
- "@oh-my-pi/omptype": "18.1.21",
128
- "@oh-my-pi/pi-catalog": "18.1.21",
129
- "@oh-my-pi/pi-natives": "18.1.21",
130
- "@oh-my-pi/pi-utils": "18.1.21",
131
- "@oh-my-pi/pi-wire": "18.1.21"
127
+ "@oh-my-pi/omptype": "18.1.22",
128
+ "@oh-my-pi/pi-catalog": "18.1.22",
129
+ "@oh-my-pi/pi-natives": "18.1.22",
130
+ "@oh-my-pi/pi-utils": "18.1.22",
131
+ "@oh-my-pi/pi-wire": "18.1.22"
132
132
  },
133
133
  "devDependencies": {
134
134
  "@types/bun": "^1.3.14"
@@ -62,6 +62,7 @@ export function buildProviderDefinition(
62
62
  ...transport,
63
63
  ...(envKeys !== undefined ? { envKeys } : {}),
64
64
  ...(policy.allowsMissingApiKey !== undefined ? { allowsMissingApiKey: policy.allowsMissingApiKey } : {}),
65
+ ...(policy.nativeAuthApis !== undefined ? { nativeAuthApis: policy.nativeAuthApis } : {}),
65
66
  ...(policy.available !== undefined ? { available: policy.available } : {}),
66
67
  ...(policy.showInLoginList !== undefined ? { showInLoginList: policy.showInLoginList } : {}),
67
68
  ...(policy.storeAs !== undefined ? { storeCredentialsAs: policy.storeAs } : {}),
@@ -69,6 +69,8 @@ export interface ProviderDefinition {
69
69
  readonly envKeys?: KeyResolver;
70
70
  /** Provider transport can authenticate without a resolved API-key string. */
71
71
  readonly allowsMissingApiKey?: boolean;
72
+ /** APIs whose provider transport resolves credentials without a stored account. */
73
+ readonly nativeAuthApis?: readonly string[];
72
74
  /** Provider-owned model normalization that must run before API-specific option mapping. */
73
75
  readonly prepareModel?: ProviderModelPreparer;
74
76
  /** Provider-owned request shaping applied before generic API dispatch. */
@@ -20,7 +20,16 @@ export type CapturedHttpErrorResponse = {
20
20
  bodyJson?: unknown;
21
21
  };
22
22
 
23
- const SENSITIVE_HEADERS = ["authorization", "x-api-key", "api-key", "cookie", "set-cookie", "proxy-authorization"];
23
+ /**
24
+ * Matches any header name whose value carries a credential, so a persisted dump
25
+ * never leaks one. A substring match — not a hand-maintained allow-list — so
26
+ * provider-specific auth headers (`x-goog-api-key`, `x-amz-security-token`, …)
27
+ * are redacted without enumerating every provider's spelling; the fixed list it
28
+ * replaced silently leaked any auth header it did not name. Redacting a benign
29
+ * header that happens to match is harmless: dumps exist to diagnose the request
30
+ * body, not its transport headers.
31
+ */
32
+ const SENSITIVE_HEADER_PATTERN = /key|token|secret|auth|credential|cookie/i;
24
33
 
25
34
  /**
26
35
  * Build the JSON persisted for a rejected request. Request fields stay at the
@@ -167,7 +176,7 @@ function redactHeaders(headers: Record<string, string> | undefined): Record<stri
167
176
 
168
177
  const redacted: Record<string, string> = {};
169
178
  for (const [key, value] of Object.entries(headers)) {
170
- if (SENSITIVE_HEADERS.includes(key.toLowerCase())) {
179
+ if (SENSITIVE_HEADER_PATTERN.test(key)) {
171
180
  redacted[key] = "[redacted]";
172
181
  continue;
173
182
  }