react-native-ai-debugger 2.9.7 → 2.10.0

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.
Files changed (103) hide show
  1. package/README.md +8 -1
  2. package/build/__tests__/unit/checkInjectedJs.test.d.ts +2 -0
  3. package/build/__tests__/unit/checkInjectedJs.test.d.ts.map +1 -0
  4. package/build/__tests__/unit/checkInjectedJs.test.js +42 -0
  5. package/build/__tests__/unit/checkInjectedJs.test.js.map +1 -0
  6. package/build/__tests__/unit/httpRequest.test.d.ts +2 -0
  7. package/build/__tests__/unit/httpRequest.test.d.ts.map +1 -0
  8. package/build/__tests__/unit/httpRequest.test.js +127 -0
  9. package/build/__tests__/unit/httpRequest.test.js.map +1 -0
  10. package/build/__tests__/unit/overlayAdoption.test.d.ts +2 -0
  11. package/build/__tests__/unit/overlayAdoption.test.d.ts.map +1 -0
  12. package/build/__tests__/unit/overlayAdoption.test.js +38 -0
  13. package/build/__tests__/unit/overlayAdoption.test.js.map +1 -0
  14. package/build/__tests__/unit/pressabilityAudit.test.d.ts +2 -0
  15. package/build/__tests__/unit/pressabilityAudit.test.d.ts.map +1 -0
  16. package/build/__tests__/unit/pressabilityAudit.test.js +96 -0
  17. package/build/__tests__/unit/pressabilityAudit.test.js.map +1 -0
  18. package/build/__tests__/unit/redact.test.d.ts +2 -0
  19. package/build/__tests__/unit/redact.test.d.ts.map +1 -0
  20. package/build/__tests__/unit/redact.test.js +98 -0
  21. package/build/__tests__/unit/redact.test.js.map +1 -0
  22. package/build/__tests__/unit/requestDetailsInclude.test.js +25 -3
  23. package/build/__tests__/unit/requestDetailsInclude.test.js.map +1 -1
  24. package/build/__tests__/unit/requestDetailsProjection.test.js +75 -1
  25. package/build/__tests__/unit/requestDetailsProjection.test.js.map +1 -1
  26. package/build/__tests__/unit/tapAndroidStatusBarInset.test.d.ts +2 -0
  27. package/build/__tests__/unit/tapAndroidStatusBarInset.test.d.ts.map +1 -0
  28. package/build/__tests__/unit/tapAndroidStatusBarInset.test.js +139 -0
  29. package/build/__tests__/unit/tapAndroidStatusBarInset.test.js.map +1 -0
  30. package/build/__tests__/unit/tapDuration.test.js +2 -2
  31. package/build/__tests__/unit/tapDuration.test.js.map +1 -1
  32. package/build/__tests__/unit/untrustedDataRule.test.d.ts +2 -0
  33. package/build/__tests__/unit/untrustedDataRule.test.d.ts.map +1 -0
  34. package/build/__tests__/unit/untrustedDataRule.test.js +32 -0
  35. package/build/__tests__/unit/untrustedDataRule.test.js.map +1 -0
  36. package/build/__tests__/unit/vault.test.d.ts +2 -0
  37. package/build/__tests__/unit/vault.test.d.ts.map +1 -0
  38. package/build/__tests__/unit/vault.test.js +116 -0
  39. package/build/__tests__/unit/vault.test.js.map +1 -0
  40. package/build/__tests__/unit/vaultCapture.test.d.ts +2 -0
  41. package/build/__tests__/unit/vaultCapture.test.d.ts.map +1 -0
  42. package/build/__tests__/unit/vaultCapture.test.js +47 -0
  43. package/build/__tests__/unit/vaultCapture.test.js.map +1 -0
  44. package/build/__tests__/unit/vaultSlots.test.d.ts +2 -0
  45. package/build/__tests__/unit/vaultSlots.test.d.ts.map +1 -0
  46. package/build/__tests__/unit/vaultSlots.test.js +64 -0
  47. package/build/__tests__/unit/vaultSlots.test.js.map +1 -0
  48. package/build/__tests__/unit/vaultTools.test.d.ts +2 -0
  49. package/build/__tests__/unit/vaultTools.test.d.ts.map +1 -0
  50. package/build/__tests__/unit/vaultTools.test.js +49 -0
  51. package/build/__tests__/unit/vaultTools.test.js.map +1 -0
  52. package/build/core/guides.d.ts +1 -0
  53. package/build/core/guides.d.ts.map +1 -1
  54. package/build/core/guides.js +41 -6
  55. package/build/core/guides.js.map +1 -1
  56. package/build/core/httpRequest.d.ts +18 -0
  57. package/build/core/httpRequest.d.ts.map +1 -0
  58. package/build/core/httpRequest.js +95 -0
  59. package/build/core/httpRequest.js.map +1 -0
  60. package/build/core/injected/overlayAdoption.d.ts +19 -0
  61. package/build/core/injected/overlayAdoption.d.ts.map +1 -0
  62. package/build/core/injected/overlayAdoption.js +17 -0
  63. package/build/core/injected/overlayAdoption.js.map +1 -0
  64. package/build/core/network.d.ts +1 -1
  65. package/build/core/network.d.ts.map +1 -1
  66. package/build/core/network.js +19 -10
  67. package/build/core/network.js.map +1 -1
  68. package/build/core/redact.d.ts +6 -0
  69. package/build/core/redact.d.ts.map +1 -0
  70. package/build/core/redact.js +78 -0
  71. package/build/core/redact.js.map +1 -0
  72. package/build/core/register.d.ts.map +1 -1
  73. package/build/core/register.js +14 -0
  74. package/build/core/register.js.map +1 -1
  75. package/build/core/screenState.d.ts +18 -0
  76. package/build/core/screenState.d.ts.map +1 -1
  77. package/build/core/screenState.js +138 -7
  78. package/build/core/screenState.js.map +1 -1
  79. package/build/core/vault.d.ts +21 -0
  80. package/build/core/vault.d.ts.map +1 -0
  81. package/build/core/vault.js +168 -0
  82. package/build/core/vault.js.map +1 -0
  83. package/build/core/vaultCapture.d.ts +2 -0
  84. package/build/core/vaultCapture.d.ts.map +1 -0
  85. package/build/core/vaultCapture.js +38 -0
  86. package/build/core/vaultCapture.js.map +1 -0
  87. package/build/index.d.ts +1 -0
  88. package/build/index.d.ts.map +1 -1
  89. package/build/index.js +11 -8
  90. package/build/index.js.map +1 -1
  91. package/build/pro/tap.d.ts.map +1 -1
  92. package/build/pro/tap.js +7 -3
  93. package/build/pro/tap.js.map +1 -1
  94. package/build/tools/metaTools.d.ts.map +1 -1
  95. package/build/tools/metaTools.js +36 -0
  96. package/build/tools/metaTools.js.map +1 -1
  97. package/build/tools/networkTools.js +1 -1
  98. package/build/tools/networkTools.js.map +1 -1
  99. package/build/tools/requestTools.d.ts.map +1 -1
  100. package/build/tools/requestTools.js +49 -1
  101. package/build/tools/requestTools.js.map +1 -1
  102. package/package.json +3 -3
  103. package/tools.json +19 -2
package/README.md CHANGED
@@ -50,6 +50,13 @@ Linking is also how [ExecBro Pro](#pricing) attaches to your installation, if yo
50
50
  - **Accessibility Inspection** - Query UI hierarchy to find elements by text, label, or resource ID
51
51
  - **OCR Text Extraction** - Extract visible text with tap-ready coordinates via Google Cloud Vision (works on any screen content)
52
52
 
53
+ ### Credential Safety
54
+
55
+ - **Secrets never enter the transcript** - Every tool's output passes one redaction chokepoint, so a token is replaced by a handle (`[secret:auth_api.acme.io]`) whether it appears in a network header, a Redux store, a log line or a URL. Credential headers are matched by pattern rather than a fixed list, so vendor-namespaced ones (`x-shopify-access-token`, `x-goog-api-key`, `x-hasura-admin-secret`) are covered too, while `x-request-id` and `x-idempotency-key` are deliberately left alone. There is no per-call escape: `EXECBRO_REDACT=off` is set by a human and needs a restart
56
+ - **Use a credential without reading it** - `list_secrets` names the handles; `http_request({auth:{secret:"api.acme.io"}})` substitutes the value host-side and issues the request from your machine, and `vault_capture` reads a token out of the app straight into the vault when no captured request revealed one. Each credential is bound to the origin it was observed on and refused elsewhere; the vault is memory-only
57
+ - **Server- vs client-side, isolated** - `http_request` runs from the host with none of the app's TLS trust, proxy, cookie jar or mock rules; `app_request` runs inside the app with all of them. Comparing the two is how you tell a backend bug from a client one — and a 401 from the host where the app succeeds is itself the answer that the backend enforces attestation
58
+ - **App data is treated as data** - The server tells every connecting agent that logs, payloads, component trees and eval results are shaped by whatever the app talked to, and are never to be followed as instructions
59
+
53
60
  ### Multi-Device Debugging
54
61
 
55
62
  - **Connect All Devices** - `scan_metro` automatically discovers and connects to all Bridgeless targets on each Metro port
@@ -170,7 +177,7 @@ See the [full tool reference](docs/tools.md) for all tools with descriptions. Ke
170
177
  | [Device Interaction](docs/device-interaction.md) | Unified `tap`, platform-specific gestures, text input, key events |
171
178
  | [OCR Text Extraction](docs/ocr.md) | Cloud Vision OCR, offline fallback, language config, workflows |
172
179
  | [Claude Code Skills](docs/skills.md) | Pre-built skills for session setup, debugging, and automation |
173
- | [Full Tool Reference](docs/tools.md) | Complete list of all 58 tools with descriptions |
180
+ | [Full Tool Reference](docs/tools.md) | Complete list of all 63 tools with descriptions |
174
181
 
175
182
  ## How It Works
176
183
 
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=checkInjectedJs.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkInjectedJs.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/checkInjectedJs.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,42 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { findEatenEscapes } from "../../../scripts/check-injected-js.mjs";
3
+ describe("findEatenEscapes", () => {
4
+ it("flags a regex escape that the template literal will eat", () => {
5
+ const found = findEatenEscapes("const x = `var COUNT = /^\\d{1,3}$/;`;");
6
+ expect(found).toHaveLength(1);
7
+ expect(found[0].sequence).toBe("\\d");
8
+ });
9
+ it("accepts the doubled form that survives to the device", () => {
10
+ expect(findEatenEscapes("const x = `var COUNT = /^\\\\d{1,3}$/;`;")).toHaveLength(0);
11
+ });
12
+ it("leaves legitimate string escapes alone", () => {
13
+ expect(findEatenEscapes('const x = `var s = "a\\nb\\tc\\"d";`;')).toHaveLength(0);
14
+ });
15
+ it("ignores regexes in ordinary code outside any template literal", () => {
16
+ expect(findEatenEscapes("const re = /^\\d+$/;\nconst s = 'a\\db';")).toHaveLength(0);
17
+ });
18
+ it("returns to ordinary code inside a ${} interpolation", () => {
19
+ expect(findEatenEscapes("const x = `prefix ${ /^\\d+$/.source } suffix`;")).toHaveLength(0);
20
+ });
21
+ it("resumes checking after an interpolation closes", () => {
22
+ const found = findEatenEscapes("const x = `${a} tail /^\\w+$/`;");
23
+ expect(found).toHaveLength(1);
24
+ expect(found[0].sequence).toBe("\\w");
25
+ });
26
+ it("handles nested braces inside an interpolation without losing its place", () => {
27
+ const found = findEatenEscapes("const x = `${ f({ a: 1 }) } /^\\s+$/`;");
28
+ expect(found).toHaveLength(1);
29
+ expect(found[0].sequence).toBe("\\s");
30
+ });
31
+ it("skips comments and quoted strings that contain backticks", () => {
32
+ const src = "// see `occludes` for the inverse\nconst s = 'a `b` c';\nconst re = /^\\d$/;";
33
+ expect(findEatenEscapes(src)).toHaveLength(0);
34
+ });
35
+ it("reports the line the escape is on", () => {
36
+ expect(findEatenEscapes("const a = 1;\nconst b = 2;\nconst x = `/^\\d$/`;")[0].line).toBe(3);
37
+ });
38
+ it("finds every occurrence, not just the first", () => {
39
+ expect(findEatenEscapes("const x = `/^\\d$/ and /^\\w$/ and /^\\s$/`;")).toHaveLength(3);
40
+ });
41
+ });
42
+ //# sourceMappingURL=checkInjectedJs.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkInjectedJs.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/checkInjectedJs.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAU1E,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QAC/D,MAAM,KAAK,GAAG,gBAAgB,CAAC,wCAAwC,CAAC,CAAC;QACzE,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC5D,MAAM,CAAC,gBAAgB,CAAC,0CAA0C,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,gBAAgB,CAAC,uCAAuC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QAErE,MAAM,CAAC,gBAAgB,CAAC,0CAA0C,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAE3D,MAAM,CAAC,gBAAgB,CAAC,iDAAiD,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACtD,MAAM,KAAK,GAAG,gBAAgB,CAAC,iCAAiC,CAAC,CAAC;QAClE,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAC9E,MAAM,KAAK,GAAG,gBAAgB,CAAC,wCAAwC,CAAC,CAAC;QACzE,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAGhE,MAAM,GAAG,GAAG,8EAA8E,CAAC;QAC3F,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,gBAAgB,CAAC,kDAAkD,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QAClD,MAAM,CAAC,gBAAgB,CAAC,8CAA8C,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC7F,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=httpRequest.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"httpRequest.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/httpRequest.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,127 @@
1
+ import { describe, it, expect, beforeEach, afterEach, jest } from "@jest/globals";
2
+ import { resolveAuth, issueHttpRequest } from "../../core/httpRequest.js";
3
+ import { vaultAdd, resetVaultForTests } from "../../core/vault.js";
4
+ import { UserInputError } from "../../core/errors.js";
5
+ const TOKEN = "opaque-session-id-abcdefgh";
6
+ const DEAD_JWT = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjEwMDAwMDAwMDB9.Zm9vYmFyc2lnbmF0dXJlZm9vYmFy";
7
+ function mockFetch(body, init = {}) {
8
+ const res = new Response(body, {
9
+ status: init.status ?? 200,
10
+ headers: init.headers ?? { "content-type": "application/json" },
11
+ });
12
+ const spy = jest.fn(async () => res);
13
+ globalThis.fetch = spy;
14
+ return spy;
15
+ }
16
+ const realFetch = globalThis.fetch;
17
+ afterEach(() => {
18
+ globalThis.fetch = realFetch;
19
+ });
20
+ describe("resolveAuth origin binding", () => {
21
+ beforeEach(resetVaultForTests);
22
+ it("attaches a credential to its own origin", () => {
23
+ vaultAdd(TOKEN, "auth", "https://api.acme.io/v1/me");
24
+ const { header } = resolveAuth({ secret: "api.acme.io" }, "https://api.acme.io/v1/orders");
25
+ expect(header).toBe(`Bearer ${TOKEN}`);
26
+ });
27
+ it("refuses to send a credential to a different origin, which is the exfiltration case", () => {
28
+ vaultAdd(TOKEN, "auth", "https://api.acme.io/v1/me");
29
+ expect(() => resolveAuth({ secret: "api.acme.io" }, "https://evil.com/collect")).toThrow(UserInputError);
30
+ try {
31
+ resolveAuth({ secret: "api.acme.io" }, "https://evil.com/collect");
32
+ }
33
+ catch (e) {
34
+ expect(e.message).toContain("api.acme.io");
35
+ expect(e.message).toContain("evil.com");
36
+ expect(e.message).not.toContain(TOKEN);
37
+ }
38
+ });
39
+ it("refuses a handle pointing at another origin, so a handle is no way around binding", () => {
40
+ const handle = vaultAdd(TOKEN, "auth", "https://api.acme.io/v1/me");
41
+ expect(() => resolveAuth({ secret: handle }, "https://evil.com/collect")).toThrow(UserInputError);
42
+ });
43
+ it("names the unknown secret without inventing one", () => {
44
+ expect(() => resolveAuth({ secret: "api.acme.io" }, "https://api.acme.io/x")).toThrow(/no credential/i);
45
+ });
46
+ it("returns a staleness note for an expired credential rather than failing silently", () => {
47
+ vaultAdd(DEAD_JWT, "auth", "https://api.acme.io/v1/me");
48
+ const { header, note } = resolveAuth({ secret: "api.acme.io" }, "https://api.acme.io/v1/orders");
49
+ expect(header).toBe(`Bearer ${DEAD_JWT}`);
50
+ expect(note).toContain("expired");
51
+ });
52
+ it("attaches nothing when no auth was asked for", () => {
53
+ expect(resolveAuth(undefined, "https://api.acme.io/x")).toEqual({});
54
+ });
55
+ });
56
+ describe("issueHttpRequest", () => {
57
+ beforeEach(resetVaultForTests);
58
+ it("rejects a non-HTTP scheme", async () => {
59
+ await expect(issueHttpRequest({ method: "GET", url: "file:///etc/passwd" })).rejects.toThrow(UserInputError);
60
+ });
61
+ it("rejects a malformed URL", async () => {
62
+ await expect(issueHttpRequest({ method: "GET", url: "not a url" })).rejects.toThrow(UserInputError);
63
+ });
64
+ it("sends the resolved credential and renders the response", async () => {
65
+ vaultAdd(TOKEN, "auth", "https://api.acme.io/v1/me");
66
+ const spy = mockFetch(JSON.stringify({ ok: true }));
67
+ const out = await issueHttpRequest({
68
+ method: "GET",
69
+ url: "https://api.acme.io/v1/orders",
70
+ auth: { secret: "api.acme.io" },
71
+ });
72
+ const init = spy.mock.calls[0][1];
73
+ expect(init.headers.Authorization).toBe(`Bearer ${TOKEN}`);
74
+ expect(out).toContain("200");
75
+ expect(out).toContain('"ok":true');
76
+ });
77
+ it("never renders the credential it just sent", async () => {
78
+ vaultAdd(TOKEN, "auth", "https://api.acme.io/v1/me");
79
+ mockFetch(JSON.stringify({ received: { authorization: `Bearer ${TOKEN}` } }));
80
+ const out = await issueHttpRequest({
81
+ method: "GET",
82
+ url: "https://api.acme.io/v1/echo",
83
+ auth: { secret: "api.acme.io" },
84
+ });
85
+ expect(out).not.toContain(TOKEN);
86
+ expect(out).toContain("[secret:auth_api.acme.io]");
87
+ });
88
+ it("serialises an object body as JSON and sets the content type", async () => {
89
+ const spy = mockFetch("{}");
90
+ await issueHttpRequest({ method: "POST", url: "https://api.acme.io/v1/x", body: { qty: 2 } });
91
+ const init = spy.mock.calls[0][1];
92
+ expect(init.body).toBe('{"qty":2}');
93
+ expect(init.headers["Content-Type"]).toBe("application/json");
94
+ });
95
+ it("sends a string body verbatim without imposing a content type", async () => {
96
+ const spy = mockFetch("{}");
97
+ await issueHttpRequest({
98
+ method: "POST",
99
+ url: "https://api.acme.io/v1/x",
100
+ body: "a=1&b=2",
101
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
102
+ });
103
+ const init = spy.mock.calls[0][1];
104
+ expect(init.body).toBe("a=1&b=2");
105
+ expect(init.headers["Content-Type"]).toBe("application/x-www-form-urlencoded");
106
+ });
107
+ it("surfaces the staleness note through the WARNING channel", async () => {
108
+ vaultAdd(DEAD_JWT, "auth", "https://api.acme.io/v1/me");
109
+ mockFetch(JSON.stringify({ error: "unauthorized" }), { status: 401 });
110
+ const out = await issueHttpRequest({
111
+ method: "GET",
112
+ url: "https://api.acme.io/v1/orders",
113
+ auth: { secret: "api.acme.io" },
114
+ });
115
+ expect(out).toContain("WARNING:");
116
+ expect(out).toContain("expired");
117
+ });
118
+ it("reports a transport failure as a message, not an unhandled rejection", async () => {
119
+ globalThis.fetch = jest.fn(async () => {
120
+ throw new Error("getaddrinfo ENOTFOUND api.acme.io");
121
+ });
122
+ const out = await issueHttpRequest({ method: "GET", url: "https://api.acme.io/v1/x" });
123
+ expect(out).toContain("Request failed");
124
+ expect(out).toContain("ENOTFOUND");
125
+ });
126
+ });
127
+ //# sourceMappingURL=httpRequest.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"httpRequest.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/httpRequest.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=overlayAdoption.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlayAdoption.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/overlayAdoption.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { adoptsByContainment } from "../../core/injected/overlayAdoption.js";
3
+ const overlay = { hasContent: true, enterIdx: 10, contentBounds: { x: 0, y: 0, width: 1000, height: 2000 } };
4
+ const boxInside = { x: 100, y: 100, width: 200, height: 80 };
5
+ describe("adoptsByContainment", () => {
6
+ it("adopts content painted after the overlay and inside its rect", () => {
7
+ expect(adoptsByContainment({ overlayIdx: null, paintIdx: 20, bounds: boxInside }, overlay)).toBe(true);
8
+ });
9
+ it("refuses a pressable painted before the overlay", () => {
10
+ expect(adoptsByContainment({ overlayIdx: null, paintIdx: 3, bounds: boxInside }, overlay)).toBe(false);
11
+ });
12
+ it("refuses a pressable painted at the overlay's own entry point", () => {
13
+ expect(adoptsByContainment({ overlayIdx: null, paintIdx: 10, bounds: boxInside }, overlay)).toBe(false);
14
+ });
15
+ it("leaves a pressable that ancestry already assigned", () => {
16
+ expect(adoptsByContainment({ overlayIdx: 2, paintIdx: 20, bounds: boxInside }, overlay)).toBe(false);
17
+ });
18
+ it("refuses when the overlay has no usable content rect", () => {
19
+ expect(adoptsByContainment({ overlayIdx: null, paintIdx: 20, bounds: boxInside }, { ...overlay, hasContent: false })).toBe(false);
20
+ });
21
+ it("refuses when the overlay was never entered during the walk", () => {
22
+ expect(adoptsByContainment({ overlayIdx: null, paintIdx: 20, bounds: boxInside }, { ...overlay, enterIdx: -1 })).toBe(false);
23
+ });
24
+ it("refuses a pressable that is only partly inside the content rect", () => {
25
+ const straddling = { x: 900, y: 100, width: 400, height: 80 };
26
+ expect(adoptsByContainment({ overlayIdx: null, paintIdx: 20, bounds: straddling }, overlay)).toBe(false);
27
+ });
28
+ it("accepts a pressable flush with the content rect edges", () => {
29
+ const flush = { x: 0, y: 0, width: 1000, height: 2000 };
30
+ expect(adoptsByContainment({ overlayIdx: null, paintIdx: 20, bounds: flush }, overlay)).toBe(true);
31
+ });
32
+ it("is emitted as plain JS with no TypeScript left in it", () => {
33
+ const src = adoptsByContainment.toString();
34
+ expect(src).not.toContain("?.");
35
+ expect(src).not.toMatch(/:\s*(number|boolean|string)\b/);
36
+ });
37
+ });
38
+ //# sourceMappingURL=overlayAdoption.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlayAdoption.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/overlayAdoption.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pressabilityAudit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pressabilityAudit.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/pressabilityAudit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,96 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { formatPressabilityAudit } from "../../core/screenState.js";
3
+ describe("formatPressabilityAudit", () => {
4
+ it("says nothing when every marker survived", () => {
5
+ expect(formatPressabilityAudit({ markerTotal: 35, markerHiddenCount: 0, markerUnmeasurableCount: 0 })).toBeNull();
6
+ });
7
+ it("says nothing when there are no markers at all", () => {
8
+ expect(formatPressabilityAudit({})).toBeNull();
9
+ expect(formatPressabilityAudit({ markerTotal: 0, markerUnmeasurableCount: 0 })).toBeNull();
10
+ });
11
+ it("leads with unmeasurable targets, which are the anomalous ones", () => {
12
+ const note = formatPressabilityAudit({
13
+ markerTotal: 20,
14
+ markerHiddenCount: 0,
15
+ markerUnmeasurableCount: 3,
16
+ markerSkipped: [{ id: "sheet-confirm", why: "host view is not measurable" }]
17
+ });
18
+ expect(note).toContain("3 of 20");
19
+ expect(note).toContain("no measurable host view");
20
+ expect(note).toContain("sheet-confirm");
21
+ expect(note).toContain("re-read");
22
+ });
23
+ it("mentions hidden pruning alongside, without burying the anomaly", () => {
24
+ const note = formatPressabilityAudit({
25
+ markerTotal: 40,
26
+ markerHiddenCount: 12,
27
+ markerUnmeasurableCount: 2,
28
+ markerSkipped: [{ id: "confirm-btn", why: "host view is not measurable" }]
29
+ });
30
+ expect(note.indexOf("2 of 40")).toBeLessThan(note.indexOf("12 more"));
31
+ });
32
+ it("reports hidden-only pruning as normal, not as a problem", () => {
33
+ const note = formatPressabilityAudit({
34
+ markerTotal: 40,
35
+ markerHiddenCount: 15,
36
+ markerUnmeasurableCount: 0,
37
+ markerSkipped: [{ id: "settings-row", why: "pruned as hidden by Screen" }]
38
+ });
39
+ expect(note).toContain("normally correct");
40
+ expect(note).toContain("Screen");
41
+ expect(note).not.toContain("NOT listed");
42
+ });
43
+ it("names the pruning rule so an unexpected pruner is identifiable", () => {
44
+ const note = formatPressabilityAudit({
45
+ markerTotal: 9,
46
+ markerHiddenCount: 4,
47
+ markerUnmeasurableCount: 0,
48
+ markerSkipped: [{ id: "buy-now", why: "pruned as hidden by BottomSheetModal" }]
49
+ });
50
+ expect(note).toContain("BottomSheetModal");
51
+ expect(note).toContain("buy-now");
52
+ });
53
+ it("caps the sample list so a broken screen cannot flood the output", () => {
54
+ const many = Array.from({ length: 12 }, (_, i) => ({ id: `btn-${i}`, why: "host view is not measurable" }));
55
+ const note = formatPressabilityAudit({
56
+ markerTotal: 30,
57
+ markerHiddenCount: 0,
58
+ markerUnmeasurableCount: 12,
59
+ markerSkipped: many
60
+ });
61
+ expect(note).toContain("btn-5");
62
+ expect(note).not.toContain("btn-6");
63
+ });
64
+ });
65
+ describe("formatPressabilityAudit — overlay reported empty", () => {
66
+ it("flags an overlay listed with no pressables while targets exist", () => {
67
+ const note = formatPressabilityAudit({
68
+ markerTotal: 47,
69
+ markerHiddenCount: 0,
70
+ markerUnmeasurableCount: 0,
71
+ emptyOverlayGroups: ["BottomSheet"]
72
+ });
73
+ expect(note).toContain("BottomSheet");
74
+ expect(note).toContain("47 press target(s)");
75
+ expect(note).toContain("grouping fault");
76
+ });
77
+ it("takes precedence over routine pruning counts", () => {
78
+ const note = formatPressabilityAudit({
79
+ markerTotal: 35,
80
+ markerHiddenCount: 22,
81
+ markerUnmeasurableCount: 0,
82
+ emptyOverlayGroups: ["BottomSheet"]
83
+ });
84
+ expect(note).toContain("grouping fault");
85
+ expect(note).not.toContain("normally correct");
86
+ });
87
+ it("stays silent for a screen whose overlays all carry content", () => {
88
+ expect(formatPressabilityAudit({
89
+ markerTotal: 35,
90
+ markerHiddenCount: 0,
91
+ markerUnmeasurableCount: 0,
92
+ emptyOverlayGroups: []
93
+ })).toBeNull();
94
+ });
95
+ });
96
+ //# sourceMappingURL=pressabilityAudit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pressabilityAudit.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/pressabilityAudit.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=redact.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/redact.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,98 @@
1
+ import { redactSecrets } from "../../core/redact.js";
2
+ import { resetVaultForTests, vaultAdd } from "../../core/vault.js";
3
+ const JWT = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4ifQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
4
+ describe("redactSecrets", () => {
5
+ beforeEach(resetVaultForTests);
6
+ it("renders a JWT as a stable handle and never as its value", () => {
7
+ const out = redactSecrets(`token was ${JWT} ok`);
8
+ expect(out).not.toContain(JWT);
9
+ expect(out).toContain("[secret:jwt_app]");
10
+ });
11
+ it("gives the same value the same handle across two calls, which is cross-sink identity", () => {
12
+ const fromState = redactSecrets(`{"accessToken":"${JWT}"}`);
13
+ const fromHeader = redactSecrets(`Authorization: Bearer ${JWT}`);
14
+ expect(fromState).toContain("[secret:jwt_app]");
15
+ expect(fromHeader).toContain("[secret:jwt_app]");
16
+ });
17
+ it("masks a value seen once by exact match afterwards, with no shape or key to match", () => {
18
+ redactSecrets("Authorization: Bearer opaque-session-id-abcdefgh");
19
+ const later = redactSecrets('ws frame: {"t":"opaque-session-id-abcdefgh"}', { catalog: false });
20
+ expect(later).not.toContain("opaque-session-id-abcdefgh");
21
+ expect(later).toContain("[secret:auth_app]");
22
+ });
23
+ it("names a provider key by its verified shape", () => {
24
+ expect(redactSecrets("key sk_live_51H8xKzAbCdEfGhIjKlMnOp here")).toContain("[secret:stripe_app]");
25
+ expect(redactSecrets("AKIAIOSFODNN7EXAMPLE")).toContain("[secret:aws_app]");
26
+ });
27
+ it("does not re-redact a marker a previous rule just produced", () => {
28
+ const out = redactSecrets(`{"accessToken":"${JWT}"}`);
29
+ expect(out).toContain('"accessToken":"[secret:jwt_app]"');
30
+ expect(out).not.toContain("[redacted secret");
31
+ });
32
+ it("keeps the auth scheme but not the credential", () => {
33
+ const out = redactSecrets("Authorization: Bearer abcdefghijklmnopqrstuvwxyz");
34
+ expect(out).toContain("Bearer [secret:auth_app]");
35
+ expect(out).not.toContain("abcdefghijklmnopqrstuvwxyz");
36
+ });
37
+ it("does not vault key-name matches, which are below the entry bar", () => {
38
+ const out = redactSecrets("GET https://api.example.com/v1/me?access_token=s3cr3tvalue&page=2");
39
+ expect(out).toContain("?access_token=[redacted secret,");
40
+ expect(out).toContain("&page=2");
41
+ expect(out).not.toContain("s3cr3tvalue");
42
+ expect(out).not.toContain("[secret:");
43
+ });
44
+ it("redacts secret-named JSON fields, which covers redux state", () => {
45
+ const out = redactSecrets('{"auth":{"access_token":"opaque-session-1234","user":"bob"}}');
46
+ expect(out).toContain('"access_token":"[redacted secret,');
47
+ expect(out).not.toContain("opaque-session-1234");
48
+ expect(out).toContain('"user":"bob"');
49
+ });
50
+ it("no longer discloses the last four characters", () => {
51
+ const out = redactSecrets('{"access_token":"opaque-session-1234"}');
52
+ expect(out).not.toContain("1234]");
53
+ expect(out).toContain("[redacted secret, 19 chars]");
54
+ });
55
+ it("leaves placeholders alone, because an absent token is the answer", () => {
56
+ expect(redactSecrets("refresh_token: undefined")).toBe("refresh_token: undefined");
57
+ });
58
+ it("appends a catalog when a handle was emitted, and nothing otherwise", () => {
59
+ expect(redactSecrets(`Bearer ${JWT}`)).toContain("--- secrets referenced above ---");
60
+ expect(redactSecrets("plain text")).toBe("plain text");
61
+ });
62
+ it("omits the catalog when asked, for telemetry fields", () => {
63
+ const out = redactSecrets(`Bearer ${JWT}`, { catalog: false });
64
+ expect(out).not.toContain("--- secrets referenced above ---");
65
+ expect(out).toContain("[secret:jwt_app]");
66
+ });
67
+ });
68
+ describe("catalog coverage for handles emitted elsewhere", () => {
69
+ beforeEach(resetVaultForTests);
70
+ it("explains a handle that redactHeaderValue rendered, not this call", () => {
71
+ const handle = vaultAdd("opaque-session-id-abcdefgh", "auth", "https://gifted.fyi/app-api/me");
72
+ const out = redactSecrets(`Authorization: Bearer [secret:${handle}]`);
73
+ expect(out).toContain("--- secrets referenced above ---");
74
+ expect(out).toContain("auth_gifted.fyi: auth seen on gifted.fyi");
75
+ });
76
+ });
77
+ describe("a value that already carries a handle", () => {
78
+ beforeEach(resetVaultForTests);
79
+ const TOKEN = "opaque-session-id-abcdefgh";
80
+ it("keeps the handle when a scheme prefix precedes it", () => {
81
+ vaultAdd(TOKEN, "auth", "https://api.acme.io/v1/me");
82
+ const out = redactSecrets(JSON.stringify({ authorization: `Bearer ${TOKEN}` }), { catalog: false });
83
+ expect(out).toContain("Bearer [secret:auth_api.acme.io]");
84
+ expect(out).not.toContain("[redacted secret");
85
+ });
86
+ it("keeps the handle among cookie attributes", () => {
87
+ vaultAdd(TOKEN, "auth", "https://api.acme.io/v1/me");
88
+ const out = redactSecrets(JSON.stringify({ cookie: `sid=${TOKEN}; path=/` }), { catalog: false });
89
+ expect(out).toContain("sid=[secret:auth_api.acme.io]; path=/");
90
+ });
91
+ it("still redacts a second, unmatched secret sitting beside a handle", () => {
92
+ vaultAdd(TOKEN, "auth", "https://api.acme.io/v1/me");
93
+ const out = redactSecrets(JSON.stringify({ authorization: `Bearer ${TOKEN} sig=OTHERSECRETVALUE1234567890` }), { catalog: false });
94
+ expect(out).not.toContain("OTHERSECRETVALUE1234567890");
95
+ expect(out).toContain("[redacted secret");
96
+ });
97
+ });
98
+ //# sourceMappingURL=redact.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/redact.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEnE,MAAM,GAAG,GACL,iIAAiI,CAAC;AAEtI,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC3B,UAAU,CAAC,kBAAkB,CAAC,CAAC;IAE/B,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QAC/D,MAAM,GAAG,GAAG,aAAa,CAAC,aAAa,GAAG,KAAK,CAAC,CAAC;QACjD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qFAAqF,EAAE,GAAG,EAAE;QAC3F,MAAM,SAAS,GAAG,aAAa,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;QAC5D,MAAM,UAAU,GAAG,aAAa,CAAC,yBAAyB,GAAG,EAAE,CAAC,CAAC;QACjE,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;QAChD,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kFAAkF,EAAE,GAAG,EAAE;QACxF,aAAa,CAAC,kDAAkD,CAAC,CAAC;QAClE,MAAM,KAAK,GAAG,aAAa,CAAC,8CAA8C,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAChG,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC;QAC1D,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QAClD,MAAM,CAAC,aAAa,CAAC,0CAA0C,CAAC,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAGnG,MAAM,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACjE,MAAM,GAAG,GAAG,aAAa,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAC;QAC1D,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACpD,MAAM,GAAG,GAAG,aAAa,CAAC,kDAAkD,CAAC,CAAC;QAC9E,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;QAClD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACtE,MAAM,GAAG,GAAG,aAAa,CAAC,mEAAmE,CAAC,CAAC;QAC/F,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC;QACzD,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QACzC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QAClE,MAAM,GAAG,GAAG,aAAa,CAAC,8DAA8D,CAAC,CAAC;QAC1F,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,mCAAmC,CAAC,CAAC;QAC3D,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QACjD,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACpD,MAAM,GAAG,GAAG,aAAa,CAAC,wCAAwC,CAAC,CAAC;QACpE,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACnC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QACxE,MAAM,CAAC,aAAa,CAAC,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC1E,MAAM,CAAC,aAAa,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAC;QACrF,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC1D,MAAM,GAAG,GAAG,aAAa,CAAC,UAAU,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/D,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAC;QAC9D,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gDAAgD,EAAE,GAAG,EAAE;IAC5D,UAAU,CAAC,kBAAkB,CAAC,CAAC;IAE/B,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAGxE,MAAM,MAAM,GAAG,QAAQ,CAAC,4BAA4B,EAAE,MAAM,EAAE,+BAA+B,CAAE,CAAC;QAChG,MAAM,GAAG,GAAG,aAAa,CAAC,iCAAiC,MAAM,GAAG,CAAC,CAAC;QACtE,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAC;QAC1D,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,0CAA0C,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACnD,UAAU,CAAC,kBAAkB,CAAC,CAAC;IAE/B,MAAM,KAAK,GAAG,4BAA4B,CAAC;IAE3C,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QACzD,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,2BAA2B,CAAC,CAAC;QAGrD,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACpG,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAC;QAC1D,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,2BAA2B,CAAC,CAAC;QACrD,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,KAAK,UAAU,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAClG,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,uCAAuC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QACxE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,2BAA2B,CAAC,CAAC;QAGrD,MAAM,GAAG,GAAG,aAAa,CACrB,IAAI,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,UAAU,KAAK,iCAAiC,EAAE,CAAC,EACnF,EAAE,OAAO,EAAE,KAAK,EAAE,CACrB,CAAC;QACF,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC;QACxD,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -1,5 +1,6 @@
1
- import { describe, it, expect } from "@jest/globals";
1
+ import { describe, it, expect, beforeEach } from "@jest/globals";
2
2
  import { formatRequestDetails, redactHeaderValue } from "../../core/network.js";
3
+ import { resetVaultForTests, vaultByHandle } from "../../core/vault.js";
3
4
  const JWT = "Bearer " + "e".repeat(1500);
4
5
  function request(overrides = {}) {
5
6
  return {
@@ -18,10 +19,11 @@ function request(overrides = {}) {
18
19
  }
19
20
  describe("get_request_details request/response split", () => {
20
21
  it("keeps a live token out of the transcript unless verbose asks for it", () => {
22
+ resetVaultForTests();
21
23
  const out = formatRequestDetails(request(), { include: "request" });
22
24
  expect(out).not.toContain(JWT);
23
- expect(out).toContain("Bearer [redacted, 1507 chars");
24
- expect(formatRequestDetails(request(), { include: "request", verbose: true })).toContain(JWT);
25
+ expect(out).toContain("Bearer [secret:auth_api.example.com]");
26
+ expect(formatRequestDetails(request(), { include: "request", verbose: true })).not.toContain(JWT);
25
27
  expect(redactHeaderValue("accept", "application/json")).toBe("application/json");
26
28
  });
27
29
  it("renders only the queried side, so narrowing does not re-dump the request", () => {
@@ -43,4 +45,24 @@ describe("get_request_details request/response split", () => {
43
45
  expect(out).toContain("t1");
44
46
  });
45
47
  });
48
+ describe("redactHeaderValue and the vault", () => {
49
+ beforeEach(resetVaultForTests);
50
+ it("names the handle after the request host", () => {
51
+ const out = redactHeaderValue("authorization", "Bearer opaque-session-id-abcdefgh", "https://api.acme.io/v1/me");
52
+ expect(out).toBe("Bearer [secret:auth_api.acme.io]");
53
+ expect(vaultByHandle("auth_api.acme.io").origin).toBe("api.acme.io");
54
+ });
55
+ it("vaults the token without its scheme, so the same value has one identity everywhere", () => {
56
+ redactHeaderValue("authorization", "Bearer opaque-session-id-abcdefgh", "https://api.acme.io/v1/me");
57
+ expect(vaultByHandle("auth_api.acme.io").value).toBe("opaque-session-id-abcdefgh");
58
+ });
59
+ it("falls back to a shape description for a short credential header", () => {
60
+ const out = redactHeaderValue("x-api-key", "abc123", "https://api.acme.io/v1/me");
61
+ expect(out).toContain("[redacted, 6 chars");
62
+ expect(out).not.toContain("abc123");
63
+ });
64
+ it("still leaves a non-credential header alone", () => {
65
+ expect(redactHeaderValue("accept", "application/json")).toBe("application/json");
66
+ });
67
+ });
46
68
  //# sourceMappingURL=requestDetailsInclude.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"requestDetailsInclude.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/requestDetailsInclude.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"requestDetailsInclude.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/requestDetailsInclude.test.ts"],"names":[],"mappings":"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"}