@respira/wordpress-mcp-server 8.3.18 → 8.3.20

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 (43) hide show
  1. package/CHANGELOG.md +89 -0
  2. package/TOOL_CATALOG.md +36 -36
  3. package/dist/__tests__/0e6bd33c-redeem-preserves-per-site-settings.test.d.ts +2 -0
  4. package/dist/__tests__/0e6bd33c-redeem-preserves-per-site-settings.test.d.ts.map +1 -0
  5. package/dist/__tests__/0e6bd33c-redeem-preserves-per-site-settings.test.js +91 -0
  6. package/dist/__tests__/0e6bd33c-redeem-preserves-per-site-settings.test.js.map +1 -0
  7. package/dist/__tests__/139f7353-put-fallback-dedicated-methods.test.d.ts +30 -0
  8. package/dist/__tests__/139f7353-put-fallback-dedicated-methods.test.d.ts.map +1 -0
  9. package/dist/__tests__/139f7353-put-fallback-dedicated-methods.test.js +162 -0
  10. package/dist/__tests__/139f7353-put-fallback-dedicated-methods.test.js.map +1 -0
  11. package/dist/__tests__/44fcf6b5-basic-auth-is-not-a-blocked-verb.test.d.ts +2 -0
  12. package/dist/__tests__/44fcf6b5-basic-auth-is-not-a-blocked-verb.test.d.ts.map +1 -0
  13. package/dist/__tests__/44fcf6b5-basic-auth-is-not-a-blocked-verb.test.js +207 -0
  14. package/dist/__tests__/44fcf6b5-basic-auth-is-not-a-blocked-verb.test.js.map +1 -0
  15. package/dist/__tests__/e105ed25-report-issue-builder-context.test.d.ts +2 -0
  16. package/dist/__tests__/e105ed25-report-issue-builder-context.test.d.ts.map +1 -0
  17. package/dist/__tests__/e105ed25-report-issue-builder-context.test.js +115 -0
  18. package/dist/__tests__/e105ed25-report-issue-builder-context.test.js.map +1 -0
  19. package/dist/__tests__/respira-outage-blamed-on-the-site.test.d.ts +2 -0
  20. package/dist/__tests__/respira-outage-blamed-on-the-site.test.d.ts.map +1 -0
  21. package/dist/__tests__/respira-outage-blamed-on-the-site.test.js +83 -0
  22. package/dist/__tests__/respira-outage-blamed-on-the-site.test.js.map +1 -0
  23. package/dist/__tests__/upload-media-path-detection.test.js +35 -1
  24. package/dist/__tests__/upload-media-path-detection.test.js.map +1 -1
  25. package/dist/__tests__/v2-negotiation-ttl-retry.test.d.ts +2 -0
  26. package/dist/__tests__/v2-negotiation-ttl-retry.test.d.ts.map +1 -0
  27. package/dist/__tests__/v2-negotiation-ttl-retry.test.js +108 -0
  28. package/dist/__tests__/v2-negotiation-ttl-retry.test.js.map +1 -0
  29. package/dist/config.d.ts.map +1 -1
  30. package/dist/config.js +59 -4
  31. package/dist/config.js.map +1 -1
  32. package/dist/server.d.ts +7 -0
  33. package/dist/server.d.ts.map +1 -1
  34. package/dist/server.js +54 -4
  35. package/dist/server.js.map +1 -1
  36. package/dist/wordpress-client.d.ts +108 -1
  37. package/dist/wordpress-client.d.ts.map +1 -1
  38. package/dist/wordpress-client.js +467 -77
  39. package/dist/wordpress-client.js.map +1 -1
  40. package/package.json +2 -2
  41. package/skills/woo-marketing-campaigns/SKILL.md +128 -0
  42. package/skills/woo-pricing-promotions/SKILL.md +119 -0
  43. package/tool-capabilities.json +92 -344
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Ticket 44fcf6b5 — a site behind server-level HTTP Basic Auth was diagnosed
3
+ * as a firewall blocking HTTP verbs, and one of the connector's own probes
4
+ * was the only request that did not send the password.
5
+ *
6
+ * Three separate confident-but-wrong statements, all of the same shape: the
7
+ * connector reported a conclusion it had no evidence for, and withheld the
8
+ * evidence it did have.
9
+ *
10
+ * 1. `isRespiraNamespaceRegistered()` probed /wp-json/respira/v2 with
11
+ * `{ Accept: 'application/json' }` and nothing else. Every other request
12
+ * carries `defaultHeaders`, which is where the site's configured
13
+ * `httpAuth` credential lives, so this one request went out logged out. It
14
+ * came back 401, the probe returned `false`, and the connector told the
15
+ * operator the Respira namespace is not registered and the plugin is
16
+ * "deactivated, deleted, or failing to load". The plugin was active the
17
+ * whole time.
18
+ *
19
+ * 2. The 401 error message asserted that "a firewall, CDN, or maintenance
20
+ * mode may be blocking API access". A 401 is an authentication challenge.
21
+ * Maintenance mode is a 503. Nothing in the response said anything about
22
+ * maintenance.
23
+ *
24
+ * 3. The same message told the operator to add `httpAuth` to their site
25
+ * config without checking whether it was already there. On the reported
26
+ * site it was, and it had been sent on the failing request.
27
+ *
28
+ * 4. `diagnose_connection` graded a 401 on OPTIONS/PUT as
29
+ * `write_method_verdict: 'blocked'` and recommended CDN/WAF method rules,
30
+ * never mentioning Basic Auth and never recording the `WWW-Authenticate`
31
+ * header that says exactly what happened.
32
+ *
33
+ * These assertions fail on unmodified main.
34
+ */
35
+ import { test, after } from 'node:test';
36
+ import assert from 'node:assert/strict';
37
+ import http from 'node:http';
38
+ import { WordPressClient } from '../wordpress-client.js';
39
+ const servers = [];
40
+ after(() => { for (const s of servers)
41
+ s.close(); });
42
+ const CHALLENGE_HTML = '<!DOCTYPE html><html><head><title>401 Authorization Required</title></head><body>Authorization Required</body></html>';
43
+ const USER = 'staging';
44
+ const PASS = 'hunter2';
45
+ const EXPECTED = 'Basic ' + Buffer.from(`${USER}:${PASS}`).toString('base64');
46
+ /**
47
+ * A site whose Basic Auth block is scoped by method — the shape that produces
48
+ * exactly the reported symptom, where reads work and every write is
49
+ * challenged (Apache `<Limit>` inside the auth block, nginx `limit_except`
50
+ * inside the protected location).
51
+ */
52
+ async function startMethodScopedBasicAuthSite(opts) {
53
+ const seen = [];
54
+ const server = http.createServer((req, res) => {
55
+ seen.push({
56
+ method: req.method || '',
57
+ url: req.url || '',
58
+ authorization: req.headers.authorization || null,
59
+ });
60
+ if (!['GET', 'HEAD'].includes(req.method || '')) {
61
+ res.writeHead(401, { 'Content-Type': 'text/html', 'WWW-Authenticate': 'Basic realm="Staging"' });
62
+ res.end(CHALLENGE_HTML);
63
+ return;
64
+ }
65
+ res.writeHead(200, { 'Content-Type': 'application/json' });
66
+ res.end(JSON.stringify({ ok: true, method: req.method }));
67
+ });
68
+ servers.push(server);
69
+ await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
70
+ const { port } = server.address();
71
+ const client = new WordPressClient({
72
+ id: 'staging',
73
+ name: 'staging',
74
+ url: `http://127.0.0.1:${port}`,
75
+ apiKey: `respira_site_${'x'.repeat(24)}`,
76
+ ...(opts.withCredentials ? { httpAuth: { username: USER, password: PASS } } : {}),
77
+ });
78
+ return { client, seen };
79
+ }
80
+ test('the namespace probe sends the configured Basic Auth credential', async () => {
81
+ // A site where EVERY request needs the password, and only /respira/v2
82
+ // exists. The probe is the request under test.
83
+ const seen = [];
84
+ const server = http.createServer((req, res) => {
85
+ seen.push({ method: req.method || '', url: req.url || '', authorization: req.headers.authorization || null });
86
+ if ((req.headers.authorization || '') !== EXPECTED) {
87
+ res.writeHead(401, { 'Content-Type': 'text/html', 'WWW-Authenticate': 'Basic realm="Staging"' });
88
+ res.end(CHALLENGE_HTML);
89
+ return;
90
+ }
91
+ res.writeHead(200, { 'Content-Type': 'application/json' });
92
+ res.end(JSON.stringify({ namespace: 'respira/v2', routes: {} }));
93
+ });
94
+ servers.push(server);
95
+ await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
96
+ const { port } = server.address();
97
+ const client = new WordPressClient({
98
+ id: 's', name: 's', url: `http://127.0.0.1:${port}`,
99
+ apiKey: `respira_site_${'x'.repeat(24)}`,
100
+ httpAuth: { username: USER, password: PASS },
101
+ });
102
+ const present = await client.isRespiraNamespaceRegistered();
103
+ const probe = seen.find((s) => s.url.includes('/wp-json/respira/v2'));
104
+ assert.ok(probe, 'the namespace probe must have been issued');
105
+ assert.equal(probe.authorization, EXPECTED, 'the namespace probe went out without the site\'s configured Basic Auth credential');
106
+ assert.equal(present, true, 'and so reported the namespace absent on a site where it is present');
107
+ });
108
+ test('a challenged namespace probe reports "could not tell", not "plugin missing"', async () => {
109
+ // No credential configured: the probe is challenged and genuinely cannot
110
+ // answer. `false` here is a claim about the customer's plugin that the
111
+ // probe has no basis for.
112
+ const server = http.createServer((_req, res) => {
113
+ res.writeHead(401, { 'Content-Type': 'text/html', 'WWW-Authenticate': 'Basic realm="Staging"' });
114
+ res.end(CHALLENGE_HTML);
115
+ });
116
+ servers.push(server);
117
+ await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
118
+ const { port } = server.address();
119
+ const client = new WordPressClient({
120
+ id: 's', name: 's', url: `http://127.0.0.1:${port}`, apiKey: `respira_site_${'x'.repeat(24)}`,
121
+ });
122
+ const present = await client.isRespiraNamespaceRegistered();
123
+ assert.equal(present, null, 'a 401 is the server declining to answer, not an answer of "absent"');
124
+ });
125
+ test('a 401 on a write does not blame maintenance mode', async () => {
126
+ const { client } = await startMethodScopedBasicAuthSite({ withCredentials: true });
127
+ const err = await client.updateMenuItem(42, { position: 2 }).then(() => null, (e) => e);
128
+ assert.ok(err, 'the write must still fail — this is about what it says, not about hiding it');
129
+ assert.equal(err.name, 'http_401_non_wordpress');
130
+ assert.ok(!/maintenance/i.test(err.message), `a 401 is an authentication challenge; maintenance mode is a 503. Message was:\n${err.message}`);
131
+ });
132
+ test('a 401 with no WWW-Authenticate header still does not invent maintenance mode', async () => {
133
+ // This is the branch that literally said "a firewall, CDN, or maintenance
134
+ // mode may be blocking API access". Some proxies strip WWW-Authenticate on
135
+ // the way back, which is exactly when the operator most needs the message
136
+ // to stick to what was observed.
137
+ const server = http.createServer((req, res) => {
138
+ if (!['GET', 'HEAD'].includes(req.method || '')) {
139
+ res.writeHead(401, { 'Content-Type': 'text/html' }); // no WWW-Authenticate
140
+ res.end(CHALLENGE_HTML);
141
+ return;
142
+ }
143
+ res.writeHead(200, { 'Content-Type': 'application/json' });
144
+ res.end(JSON.stringify({ ok: true }));
145
+ });
146
+ servers.push(server);
147
+ await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
148
+ const { port } = server.address();
149
+ const client = new WordPressClient({
150
+ id: 's', name: 's', url: `http://127.0.0.1:${port}`, apiKey: `respira_site_${'x'.repeat(24)}`,
151
+ });
152
+ const err = await client.updateMenuItem(1, { position: 1 }).then(() => null, (e) => e);
153
+ assert.ok(!/maintenance/i.test(err.message), `nothing in a 401 is evidence of maintenance mode. Message was:\n${err.message}`);
154
+ assert.match(err.message, /no WWW-Authenticate header/i, 'say what was actually missing instead of guessing what it means');
155
+ });
156
+ test('a 401 on a write says the configured credential was sent', async () => {
157
+ const { client, seen } = await startMethodScopedBasicAuthSite({ withCredentials: true });
158
+ const err = await client.updateMenuItem(42, { position: 2 }).then(() => null, (e) => e);
159
+ // The credential really was on the wire; the message must not pretend otherwise.
160
+ const write = seen.find((s) => s.method === 'PUT' || s.method === 'POST');
161
+ assert.equal(write?.authorization, EXPECTED, 'precondition: the write did carry the credential');
162
+ assert.match(err.message, /httpAuth IS configured/, `the message must say the credential was already configured and sent, not tell the operator to add it. Message was:\n${err.message}`);
163
+ assert.ok(!/^\s*"httpAuth": \{ "username": "your-user"/m.test(err.message), 'and must not hand back the boilerplate "add httpAuth" snippet they already followed');
164
+ });
165
+ test('a 401 with no httpAuth configured still tells you to add it', async () => {
166
+ const { client } = await startMethodScopedBasicAuthSite({ withCredentials: false });
167
+ const err = await client.updateMenuItem(42, { position: 2 }).then(() => null, (e) => e);
168
+ assert.match(err.message, /No httpAuth is configured/);
169
+ assert.match(err.message, /"httpAuth": \{ "username"/);
170
+ assert.match(err.message, /realm "Staging"/, 'the realm the server named is evidence and belongs in the message');
171
+ });
172
+ test('diagnose_connection calls a Basic Auth challenge an auth challenge, not a blocked verb', async () => {
173
+ const { client } = await startMethodScopedBasicAuthSite({ withCredentials: true });
174
+ const report = await client.diagnoseConnection({ probe_timeout_ms: 5000 });
175
+ assert.equal(report.write_method_verdict, 'auth_challenge', 'a 401 on PUT/OPTIONS is the server asking for a password, not the edge blocking a verb');
176
+ assert.equal(report.write_method_blocked, null, 'the verb never reached WordPress, so nothing here proves it is blocked');
177
+ assert.equal(report.http_auth_configured, true, 'whether a credential was configured is part of the evidence');
178
+ assert.equal(report.write_method_probe.put_auth_challenged, true);
179
+ assert.match(String(report.write_method_probe.put_www_authenticate || ''), /Basic/i, 'the WWW-Authenticate header is the discriminator and must be recorded');
180
+ const joined = report.recommendations.join('\n');
181
+ assert.match(joined, /authentication challenge, not a blocked HTTP verb/);
182
+ assert.ok(!/Cloudflare custom rule|Bad Bot - Action Block|Whitelisted URLs/i.test(joined), `must not send the operator into WAF method rules for a password prompt. Recommendations were:\n${joined}`);
183
+ assert.ok(!/^Write-method state is unknown/m.test(joined), 'and must not fall through to the generic unknown branch');
184
+ });
185
+ test('a genuinely blocked verb is still reported as blocked', async () => {
186
+ // Guard against the new branch swallowing the case it sits in front of:
187
+ // a 403 HTML rejection with no WWW-Authenticate is still a method block.
188
+ const server = http.createServer((req, res) => {
189
+ if (!['GET', 'HEAD'].includes(req.method || '')) {
190
+ res.writeHead(403, { 'Content-Type': 'text/html' });
191
+ res.end('<!DOCTYPE html><html><head><title>403 Forbidden</title></head><body>Forbidden</body></html>');
192
+ return;
193
+ }
194
+ res.writeHead(200, { 'Content-Type': 'application/json' });
195
+ res.end(JSON.stringify({ ok: true }));
196
+ });
197
+ servers.push(server);
198
+ await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
199
+ const { port } = server.address();
200
+ const client = new WordPressClient({
201
+ id: 's', name: 's', url: `http://127.0.0.1:${port}`, apiKey: `respira_site_${'x'.repeat(24)}`,
202
+ });
203
+ const report = await client.diagnoseConnection({ probe_timeout_ms: 5000 });
204
+ assert.equal(report.write_method_verdict, 'blocked');
205
+ assert.equal(report.write_method_blocked, true);
206
+ });
207
+ //# sourceMappingURL=44fcf6b5-basic-auth-is-not-a-blocked-verb.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"44fcf6b5-basic-auth-is-not-a-blocked-verb.test.js","sourceRoot":"","sources":["../../src/__tests__/44fcf6b5-basic-auth-is-not-a-blocked-verb.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=e105ed25-report-issue-builder-context.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"e105ed25-report-issue-builder-context.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/e105ed25-report-issue-builder-context.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Regression test for ticket e105ed25: `respira_report_issue` auto-attaches
3
+ * `builder: null` and `builder_version: null` even when the site has an
4
+ * unambiguously detected builder.
5
+ *
6
+ * Reported repro: `respira_get_builder_info` (no args) correctly returns
7
+ * `active_builder: { name: "Beaver Builder", version: "2.11.0.3" }` — the
8
+ * detection works — but the report `reportIssue()` files afterward carries
9
+ * `builder: null, builder_version: null` regardless.
10
+ *
11
+ * Root cause: `/context/builder-info` (see
12
+ * wordpress-plugin/respira-for-wordpress/includes/class-respira-context.php,
13
+ * `get_builder_info()`) returns `{ active_builder: { name, version },
14
+ * detected_builders: [...] }` — there is no top-level `name`/`version` on the
15
+ * response. `reportIssue()` in server.ts read `info?.name` / `info?.version`
16
+ * directly, which is always `undefined`. This is the exact mcp-6.19.6-era
17
+ * mistake already fixed in `extractBuilderContent` and `detectDiviVersion`
18
+ * (wordpress-client.ts), which both read `info.active_builder.name` — just
19
+ * never applied to reportIssue().
20
+ *
21
+ * Mock-adapter plumbing mirrors 429299b5-delete-post-empty-envelope.test.ts.
22
+ * global.fetch is mocked separately because reportIssue() posts to
23
+ * respira.press via fetch(), not through the axios-based WordPressClient.
24
+ */
25
+ import { test } from 'node:test';
26
+ import assert from 'node:assert/strict';
27
+ import axios from 'axios';
28
+ import { RespiraWordPressServer } from '../server.js';
29
+ let currentHandler = null;
30
+ const originalAdapter = axios.defaults.adapter;
31
+ function installMockAdapter(handler) {
32
+ currentHandler = handler;
33
+ axios.defaults.adapter = ((config) => {
34
+ if (!currentHandler) {
35
+ return Promise.reject(new Error('no mock handler installed'));
36
+ }
37
+ const r = currentHandler(config);
38
+ const response = {
39
+ status: r.status,
40
+ statusText: 'OK',
41
+ headers: { 'content-type': 'application/json' },
42
+ config,
43
+ data: r.data,
44
+ request: {},
45
+ };
46
+ if (r.status >= 200 && r.status < 300) {
47
+ return Promise.resolve(response);
48
+ }
49
+ const err = new Error(`Request failed with status code ${r.status}`);
50
+ err.isAxiosError = true;
51
+ err.response = response;
52
+ err.config = config;
53
+ return Promise.reject(err);
54
+ });
55
+ }
56
+ function restoreAdapter() {
57
+ axios.defaults.adapter = originalAdapter;
58
+ currentHandler = null;
59
+ }
60
+ const SITE = {
61
+ id: 'bb-site',
62
+ name: 'Beaver Builder Test Site',
63
+ url: 'https://beaver-example.test',
64
+ apiKey: 'respira_site_testkey1234567890',
65
+ default: true,
66
+ };
67
+ /** What the real plugin returns for a site with an unambiguous active builder. */
68
+ function builderInfoHandler(config) {
69
+ const url = config.url || '';
70
+ if (url.includes('/context/builder-info')) {
71
+ return {
72
+ status: 200,
73
+ data: {
74
+ detected_builders: [
75
+ { name: 'Beaver Builder', version: '2.11.0.3', confidence: 'high' },
76
+ { name: 'Gutenberg', version: '18.4', confidence: 'low' },
77
+ ],
78
+ active_builder: { name: 'Beaver Builder', version: '2.11.0.3' },
79
+ },
80
+ };
81
+ }
82
+ // Any other probe (version negotiation, compatibility) answers harmlessly.
83
+ return { status: 200, data: {} };
84
+ }
85
+ test('respira_report_issue attaches the detected builder instead of null (e105ed25)', async (t) => {
86
+ installMockAdapter(builderInfoHandler);
87
+ const originalFetch = globalThis.fetch;
88
+ let capturedBody = null;
89
+ globalThis.fetch = (async (_url, init) => {
90
+ capturedBody = JSON.parse(init.body);
91
+ return {
92
+ ok: true,
93
+ status: 201,
94
+ json: async () => ({ success: true, id: 42, message: 'Filed.' }),
95
+ };
96
+ });
97
+ t.after(() => {
98
+ restoreAdapter();
99
+ globalThis.fetch = originalFetch;
100
+ });
101
+ const server = new RespiraWordPressServer([SITE]);
102
+ const result = await server.dispatchToolCall('wordpress_report_issue', {
103
+ title: 'Builder writes silently no-op on this page',
104
+ brief: 'Building a page on this Beaver Builder site returns success but nothing renders.',
105
+ steps_to_reproduce: 'Called build_page with a hero section, got success: true, page stayed blank.',
106
+ severity: 'major',
107
+ });
108
+ assert.ok(capturedBody, 'the report POST body must have been captured');
109
+ assert.equal(capturedBody.builder, 'Beaver Builder', `builder must be the detected active builder name, not null (got ${JSON.stringify(capturedBody.builder)})`);
110
+ assert.equal(capturedBody.builder_version, '2.11.0.3', `builder_version must be the detected active builder version, not null (got ${JSON.stringify(capturedBody.builder_version)})`);
111
+ assert.equal(result.success, true);
112
+ assert.equal(result.context_attached.builder, 'Beaver Builder');
113
+ assert.equal(result.context_attached.builder_version, '2.11.0.3');
114
+ });
115
+ //# sourceMappingURL=e105ed25-report-issue-builder-context.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"e105ed25-report-issue-builder-context.test.js","sourceRoot":"","sources":["../../src/__tests__/e105ed25-report-issue-builder-context.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=respira-outage-blamed-on-the-site.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"respira-outage-blamed-on-the-site.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/respira-outage-blamed-on-the-site.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,83 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { classifyV2Failure, describeV2Failure } from '../wordpress-client.js';
4
+ /**
5
+ * A customer's agent printed this, and he spent hours acting on it:
6
+ *
7
+ * respira/v2 returned HTTP 500 on this site.
8
+ * The site said: Could not query the database for the schema cache. Retrying.
9
+ * The namespace is registered but the request failed server-side.
10
+ * Check wp-content/debug.log, then open .../wp-json/respira/v2/status.
11
+ *
12
+ * "Could not query the database for the schema cache. Retrying." is PostgREST
13
+ * error PGRST002. It is raised inside the Respira Supabase, reaches the plugin
14
+ * from respira.press/api/mcp/site-token/introspect, and appears nowhere in the
15
+ * WordPress plugin or in the customer's database. Every instruction in that
16
+ * message pointed at the one machine that was working.
17
+ *
18
+ * The mechanical cause here: the body carried
19
+ * `code: "respira_invalid_site_token"`, which names the Respira account service
20
+ * as the source, and classifyV2Failure kept `code` on the `auth` branch but
21
+ * dropped it on the `server` branch. describeV2Failure therefore could not tell
22
+ * a Respira outage from a genuine site-side 500.
23
+ */
24
+ const SITE = 'https://customer.example';
25
+ const err = (status, data) => ({ response: { status, data } });
26
+ /** The reported payload, byte for byte. */
27
+ const REPORTED_500 = err(500, {
28
+ code: 'respira_invalid_site_token',
29
+ message: 'Could not query the database for the schema cache. Retrying.',
30
+ });
31
+ describe('a Respira account-service failure is not the customer\'s site', () => {
32
+ it('carries the error code through the server branch, as the auth branch already did', () => {
33
+ const failure = classifyV2Failure(REPORTED_500);
34
+ assert.equal(failure.kind, 'server');
35
+ assert.equal(failure.code, 'respira_invalid_site_token', 'the code names the source of the failure and must survive classification');
36
+ });
37
+ it('does not send the reader to their own debug.log for a Respira outage', () => {
38
+ const msg = describeV2Failure(classifyV2Failure(REPORTED_500), SITE);
39
+ assert.ok(!/debug\.log/.test(msg), `sent the customer to their own logs:\n${msg}`);
40
+ });
41
+ it('says plainly that this is a Respira problem, not a site problem', () => {
42
+ const msg = describeV2Failure(classifyV2Failure(REPORTED_500), SITE);
43
+ assert.match(msg, /Respira account-service problem/i);
44
+ assert.match(msg, /not a problem with this WordPress site/i);
45
+ });
46
+ it('attributes the upstream sentence to respira.press rather than to the site', () => {
47
+ const msg = describeV2Failure(classifyV2Failure(REPORTED_500), SITE);
48
+ assert.ok(!/The site said/.test(msg), `misattributed a Respira error to the customer's site:\n${msg}`);
49
+ assert.match(msg, /respira\.press reported/i);
50
+ });
51
+ it('recognises the post-fix code the plugin now returns', () => {
52
+ const msg = describeV2Failure(classifyV2Failure(err(503, {
53
+ code: 'respira_site_token_validation_failed',
54
+ message: 'Respira could not reach its account service to validate this site. This is not a fault on your WordPress site.',
55
+ })), SITE);
56
+ assert.match(msg, /Respira account-service problem/i);
57
+ assert.ok(!/debug\.log/.test(msg), msg);
58
+ });
59
+ it('recognises the introspection endpoint\'s own unavailable code', () => {
60
+ const msg = describeV2Failure(classifyV2Failure(err(503, { code: 'introspection_unavailable', message: 'Retry in a moment.' })), SITE);
61
+ assert.match(msg, /Respira account-service problem/i);
62
+ });
63
+ });
64
+ describe('the site-side 500 message is untouched', () => {
65
+ it('a genuine site-side 500 still gets site-side guidance', () => {
66
+ const msg = describeV2Failure(classifyV2Failure(err(500, { code: 'internal_server_error', message: 'Fatal error in theme functions.php' })), SITE);
67
+ assert.match(msg, /debug\.log/, 'a real site fault still belongs in the site owner\'s logs');
68
+ assert.match(msg, /The site said: Fatal error in theme functions\.php/);
69
+ });
70
+ it('a 500 with no code at all keeps the old behaviour', () => {
71
+ const msg = describeV2Failure(classifyV2Failure(err(500)), SITE);
72
+ assert.match(msg, /debug\.log/);
73
+ });
74
+ it('a 401 carrying the same code is still an auth problem, not an outage', () => {
75
+ // A genuinely invalid or rotated token comes back 401/403. That is a real
76
+ // verdict about the credential and keeps the reconnect instructions.
77
+ const msg = describeV2Failure(classifyV2Failure(err(401, { code: 'respira_invalid_site_token', message: 'token out of date' })), SITE);
78
+ assert.match(msg, /authentication result/i);
79
+ assert.match(msg, /reconnect the site/i);
80
+ assert.ok(!/Respira account-service problem/i.test(msg), msg);
81
+ });
82
+ });
83
+ //# sourceMappingURL=respira-outage-blamed-on-the-site.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"respira-outage-blamed-on-the-site.test.js","sourceRoot":"","sources":["../../src/__tests__/respira-outage-blamed-on-the-site.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,IAAI,GAAG,0BAA0B,CAAC;AACxC,MAAM,GAAG,GAAG,CAAC,MAAc,EAAE,IAAU,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;AAE7E,2CAA2C;AAC3C,MAAM,YAAY,GAAG,GAAG,CAAC,GAAG,EAAE;IAC5B,IAAI,EAAE,4BAA4B;IAClC,OAAO,EAAE,8DAA8D;CACxE,CAAC,CAAC;AAEH,QAAQ,CAAC,+DAA+D,EAAE,GAAG,EAAE;IAC7E,EAAE,CAAC,kFAAkF,EAAE,GAAG,EAAE;QAC1F,MAAM,OAAO,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACrC,MAAM,CAAC,KAAK,CACT,OAAe,CAAC,IAAI,EACrB,4BAA4B,EAC5B,0EAA0E,CAC3E,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,GAAG,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,CAAC;QACrE,MAAM,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,yCAAyC,GAAG,EAAE,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,GAAG,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,CAAC;QACrE,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,kCAAkC,CAAC,CAAC;QACtD,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,yCAAyC,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,GAAG,EAAE;QACnF,MAAM,GAAG,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,CAAC;QACrE,MAAM,CAAC,EAAE,CACP,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,EAC1B,0DAA0D,GAAG,EAAE,CAChE,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,0BAA0B,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,GAAG,GAAG,iBAAiB,CAC3B,iBAAiB,CACf,GAAG,CAAC,GAAG,EAAE;YACP,IAAI,EAAE,sCAAsC;YAC5C,OAAO,EACL,gHAAgH;SACnH,CAAC,CACH,EACD,IAAI,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,kCAAkC,CAAC,CAAC;QACtD,MAAM,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,GAAG,GAAG,iBAAiB,CAC3B,iBAAiB,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,2BAA2B,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC,CAAC,EACjG,IAAI,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,kCAAkC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;IACtD,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,GAAG,GAAG,iBAAiB,CAC3B,iBAAiB,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAAC,CAAC,EAC7G,IAAI,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,YAAY,EAAE,2DAA2D,CAAC,CAAC;QAC7F,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,oDAAoD,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,GAAG,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACjE,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,0EAA0E;QAC1E,qEAAqE;QACrE,MAAM,GAAG,GAAG,iBAAiB,CAC3B,iBAAiB,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,4BAA4B,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC,EACjG,IAAI,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,wBAAwB,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;QACzC,MAAM,CAAC,EAAE,CAAC,CAAC,kCAAkC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -4,7 +4,7 @@ import { mkdtempSync, writeFileSync, rmSync } from 'node:fs';
4
4
  import { tmpdir } from 'node:os';
5
5
  import { join } from 'node:path';
6
6
  import { pathToFileURL } from 'node:url';
7
- import { isLocalFilePath, resolveLocalFilePath } from '../wordpress-client.js';
7
+ import { isLocalFilePath, looksLikeBase64Payload, resolveLocalFilePath } from '../wordpress-client.js';
8
8
  // Ticket 5a19d816: on Windows, respira_upload_media(file="C:/Users/.../photo.jpg")
9
9
  // fell through the local-file detection (which only matched '/', './', '../',
10
10
  // '~') into the base64 branch. Buffer.from(nonBase64, 'base64') doesn't throw,
@@ -33,6 +33,40 @@ test('isLocalFilePath: base64 payloads and data:/http(s): URLs are still NOT tre
33
33
  assert.equal(isLocalFilePath('http://example.com/photo.jpg'), false);
34
34
  assert.equal(isLocalFilePath('https://example.com/photo.jpg'), false);
35
35
  });
36
+ // Ticket 7c1cd8ac: every JPEG begins with the bytes FF D8 FF, which base64-encode
37
+ // to the four characters "/9j/". So a bare base64 JPEG always starts with a
38
+ // slash and was matched by the POSIX-absolute arm, sending the upload down the
39
+ // local-file branch. It never reached WordPress: it died with
40
+ // "File not found: <the whole payload>", which then echoed the entire image
41
+ // back to the agent inside the error message. The pre-existing base64 case in
42
+ // this file missed it only because its sample blob starts with a letter.
43
+ function base64JpegOfLength(bytes) {
44
+ const buf = Buffer.alloc(bytes);
45
+ buf[0] = 0xff;
46
+ buf[1] = 0xd8;
47
+ buf[2] = 0xff;
48
+ buf[3] = 0xe0;
49
+ for (let i = 4; i < bytes; i++)
50
+ buf[i] = (i * 37) & 0xff;
51
+ return buf.toString('base64');
52
+ }
53
+ test('isLocalFilePath: a bare base64 JPEG is a payload, not a path (starts with "/9j/")', () => {
54
+ const jpeg = base64JpegOfLength(7500);
55
+ assert.equal(jpeg.startsWith('/9j/'), true, 'precondition: JPEG base64 starts with /9j/');
56
+ assert.equal(isLocalFilePath(jpeg), false);
57
+ assert.equal(looksLikeBase64Payload(jpeg), true);
58
+ });
59
+ test('looksLikeBase64Payload: real paths are never mistaken for a payload', () => {
60
+ const longPosix = '/home/user/' + 'directory/'.repeat(40) + 'photo.jpg';
61
+ assert.equal(looksLikeBase64Payload(longPosix), false);
62
+ assert.equal(isLocalFilePath(longPosix), true);
63
+ // No extension, no dots, long: still excluded by the character-mix rule.
64
+ const noExtension = '/home/user/' + 'directory/'.repeat(40) + 'photo';
65
+ assert.equal(looksLikeBase64Payload(noExtension), false);
66
+ assert.equal(isLocalFilePath(noExtension), true);
67
+ // Short blobs stay conservative: not long enough to claim they are a payload.
68
+ assert.equal(looksLikeBase64Payload('/9j/4AAQSkZJRg=='), false);
69
+ });
36
70
  test('resolveLocalFilePath: Windows drive-letter paths pass through unchanged (no cwd corruption)', () => {
37
71
  // Regression guard: node:path's resolve() is POSIX on non-Windows hosts and
38
72
  // does not recognize "C:\..." as absolute, so running it through resolve()
@@ -1 +1 @@
1
- {"version":3,"file":"upload-media-path-detection.test.js","sourceRoot":"","sources":["../../src/__tests__/upload-media-path-detection.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"upload-media-path-detection.test.js","sourceRoot":"","sources":["../../src/__tests__/upload-media-path-detection.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=v2-negotiation-ttl-retry.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2-negotiation-ttl-retry.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/v2-negotiation-ttl-retry.test.ts"],"names":[],"mappings":""}