@open-mercato/cli 0.6.6-develop.6460.1.f94c74174c → 0.6.6-develop.6465.1.019f0fb26f

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 (60) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/agentic/guides/module-facts.json +53 -53
  3. package/dist/agentic/guides/modules/ai_assistant.md +1 -1
  4. package/dist/agentic/guides/modules/api_docs.md +1 -1
  5. package/dist/agentic/guides/modules/api_keys.md +1 -1
  6. package/dist/agentic/guides/modules/attachments.md +1 -1
  7. package/dist/agentic/guides/modules/audit_logs.md +1 -1
  8. package/dist/agentic/guides/modules/auth.md +1 -1
  9. package/dist/agentic/guides/modules/business_rules.md +1 -1
  10. package/dist/agentic/guides/modules/catalog.md +1 -1
  11. package/dist/agentic/guides/modules/channel_gmail.md +1 -1
  12. package/dist/agentic/guides/modules/channel_imap.md +1 -1
  13. package/dist/agentic/guides/modules/checkout.md +1 -1
  14. package/dist/agentic/guides/modules/communication_channels.md +1 -1
  15. package/dist/agentic/guides/modules/configs.md +1 -1
  16. package/dist/agentic/guides/modules/content.md +1 -1
  17. package/dist/agentic/guides/modules/currencies.md +1 -1
  18. package/dist/agentic/guides/modules/customer_accounts.md +1 -1
  19. package/dist/agentic/guides/modules/customers.md +1 -1
  20. package/dist/agentic/guides/modules/dashboards.md +1 -1
  21. package/dist/agentic/guides/modules/data_sync.md +1 -1
  22. package/dist/agentic/guides/modules/dictionaries.md +1 -1
  23. package/dist/agentic/guides/modules/directory.md +1 -1
  24. package/dist/agentic/guides/modules/entities.md +1 -1
  25. package/dist/agentic/guides/modules/events.md +1 -1
  26. package/dist/agentic/guides/modules/feature_toggles.md +1 -1
  27. package/dist/agentic/guides/modules/gateway_stripe.md +1 -1
  28. package/dist/agentic/guides/modules/generators.md +1 -1
  29. package/dist/agentic/guides/modules/inbox_ops.md +1 -1
  30. package/dist/agentic/guides/modules/integrations.md +1 -1
  31. package/dist/agentic/guides/modules/messages.md +1 -1
  32. package/dist/agentic/guides/modules/notifications.md +1 -1
  33. package/dist/agentic/guides/modules/onboarding.md +1 -1
  34. package/dist/agentic/guides/modules/payment_gateways.md +1 -1
  35. package/dist/agentic/guides/modules/perspectives.md +1 -1
  36. package/dist/agentic/guides/modules/planner.md +1 -1
  37. package/dist/agentic/guides/modules/portal.md +1 -1
  38. package/dist/agentic/guides/modules/progress.md +1 -1
  39. package/dist/agentic/guides/modules/query_index.md +1 -1
  40. package/dist/agentic/guides/modules/record_locks.md +1 -1
  41. package/dist/agentic/guides/modules/resources.md +1 -1
  42. package/dist/agentic/guides/modules/sales.md +1 -1
  43. package/dist/agentic/guides/modules/scheduler.md +1 -1
  44. package/dist/agentic/guides/modules/search.md +1 -1
  45. package/dist/agentic/guides/modules/security.md +1 -1
  46. package/dist/agentic/guides/modules/shipping_carriers.md +1 -1
  47. package/dist/agentic/guides/modules/sso.md +1 -1
  48. package/dist/agentic/guides/modules/staff.md +1 -1
  49. package/dist/agentic/guides/modules/storage_s3.md +1 -1
  50. package/dist/agentic/guides/modules/sync_akeneo.md +1 -1
  51. package/dist/agentic/guides/modules/sync_excel.md +1 -1
  52. package/dist/agentic/guides/modules/system_status_overlays.md +1 -1
  53. package/dist/agentic/guides/modules/translations.md +1 -1
  54. package/dist/agentic/guides/modules/webhooks.md +1 -1
  55. package/dist/agentic/guides/modules/workflows.md +1 -1
  56. package/dist/lib/testing/integration.js +185 -5
  57. package/dist/lib/testing/integration.js.map +2 -2
  58. package/package.json +5 -5
  59. package/src/lib/testing/__tests__/integration.test.ts +228 -6
  60. package/src/lib/testing/integration.ts +231 -3
@@ -1,5 +1,5 @@
1
1
  # entities — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # events — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # feature_toggles — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # gateway_stripe — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # generators — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # inbox_ops — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # integrations — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # messages — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # notifications — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # onboarding — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # payment_gateways — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # perspectives — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # planner — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # portal — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # progress — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # query_index — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # record_locks — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # resources — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # sales — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # scheduler — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # search — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # security — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # shipping_carriers — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # sso — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # staff — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # storage_s3 — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # sync_akeneo — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # sync_excel — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # system_status_overlays — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # translations — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # webhooks — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # workflows — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.6-develop.6460.1.f94c74174c — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.6-develop.6465.1.019f0fb26f — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -165,6 +165,7 @@ const FOLDER_TO_CATEGORY_CODE = {
165
165
  api: "API",
166
166
  integration: "INT"
167
167
  };
168
+ const BACKEND_BROWSER_AUTH_REDIRECT_LIMIT = 6;
168
169
  const BUILD_CACHE_STATE_VERSION = 2;
169
170
  const BUILD_CACHE_ENV_KEYS = [
170
171
  "NODE_ENV",
@@ -1064,17 +1065,195 @@ async function probeAuthenticatedApi(baseUrl) {
1064
1065
  };
1065
1066
  }
1066
1067
  }
1068
+ function splitSetCookieHeader(header) {
1069
+ return header.split(/,(?=\s*[^;,\s=]+=)/).map((value) => value.trim()).filter((value) => value.length > 0);
1070
+ }
1071
+ function getSetCookieHeaders(headers) {
1072
+ if (!headers) {
1073
+ return [];
1074
+ }
1075
+ const setCookieGetter = headers.getSetCookie;
1076
+ if (typeof setCookieGetter === "function") {
1077
+ return setCookieGetter.call(headers).map((value) => value.trim()).filter((value) => value.length > 0);
1078
+ }
1079
+ const combined = headers.get("set-cookie");
1080
+ return combined ? splitSetCookieHeader(combined) : [];
1081
+ }
1082
+ function parseSetCookiePair(header) {
1083
+ const pair = header.split(";", 1)[0]?.trim();
1084
+ if (!pair) {
1085
+ return null;
1086
+ }
1087
+ const equalsIndex = pair.indexOf("=");
1088
+ if (equalsIndex <= 0) {
1089
+ return null;
1090
+ }
1091
+ const name = pair.slice(0, equalsIndex).trim();
1092
+ if (!name) {
1093
+ return null;
1094
+ }
1095
+ return {
1096
+ name,
1097
+ value: pair.slice(equalsIndex + 1)
1098
+ };
1099
+ }
1100
+ function addSetCookieHeadersToJar(jar, headers) {
1101
+ for (const setCookieHeader of getSetCookieHeaders(headers)) {
1102
+ const pair = parseSetCookiePair(setCookieHeader);
1103
+ if (pair) {
1104
+ jar.set(pair.name, pair.value);
1105
+ }
1106
+ }
1107
+ }
1108
+ function serializeCookieJar(jar) {
1109
+ return [...jar.entries()].map(([name, value]) => `${name}=${value}`).join("; ");
1110
+ }
1111
+ function formatCookieNames(jar) {
1112
+ const names = [...jar.keys()].sort((left, right) => left.localeCompare(right));
1113
+ return names.length > 0 ? names.join(", ") : "none";
1114
+ }
1115
+ function toReadinessPath(url) {
1116
+ return url.pathname || "/";
1117
+ }
1118
+ function resolveReadinessRedirect(baseUrl, currentUrl, rawLocation) {
1119
+ const location = rawLocation?.trim();
1120
+ if (!location) {
1121
+ return { error: "missing Location header" };
1122
+ }
1123
+ if (location.startsWith("//")) {
1124
+ return { error: "protocol-relative redirect" };
1125
+ }
1126
+ let nextUrl;
1127
+ try {
1128
+ nextUrl = new URL(location, currentUrl);
1129
+ } catch {
1130
+ return { error: "invalid Location header" };
1131
+ }
1132
+ if (nextUrl.origin !== baseUrl.origin) {
1133
+ return { error: "cross-origin redirect" };
1134
+ }
1135
+ return {
1136
+ url: nextUrl,
1137
+ path: toReadinessPath(nextUrl)
1138
+ };
1139
+ }
1140
+ async function probeBackendBrowserAuth(baseUrl) {
1141
+ try {
1142
+ const base = new URL(baseUrl);
1143
+ const form = new URLSearchParams();
1144
+ form.set("email", "admin@acme.com");
1145
+ form.set("password", "secret");
1146
+ const loginResponse = await probeFetch(`${baseUrl}/api/auth/login`, {
1147
+ method: "POST",
1148
+ redirect: "manual",
1149
+ headers: {
1150
+ "Content-Type": "application/x-www-form-urlencoded"
1151
+ },
1152
+ body: form.toString()
1153
+ });
1154
+ if (!loginResponse.ok) {
1155
+ return {
1156
+ loginStatus: loginResponse.status,
1157
+ backendStatus: null,
1158
+ healthy: false,
1159
+ detail: `Backend browser auth login returned ${loginResponse.status}`
1160
+ };
1161
+ }
1162
+ const cookieJar = /* @__PURE__ */ new Map();
1163
+ addSetCookieHeadersToJar(cookieJar, loginResponse.headers);
1164
+ if (cookieJar.size === 0) {
1165
+ return {
1166
+ loginStatus: loginResponse.status,
1167
+ backendStatus: null,
1168
+ healthy: false,
1169
+ detail: "Backend browser auth login returned no cookies"
1170
+ };
1171
+ }
1172
+ let currentUrl = new URL("/backend", base);
1173
+ let backendStatus = null;
1174
+ const visitedPaths = /* @__PURE__ */ new Set();
1175
+ const trace = [];
1176
+ for (let redirectCount = 0; redirectCount <= BACKEND_BROWSER_AUTH_REDIRECT_LIMIT; redirectCount += 1) {
1177
+ const currentPath = toReadinessPath(currentUrl);
1178
+ visitedPaths.add(currentPath);
1179
+ const response = await probeFetch(currentUrl.toString(), {
1180
+ method: "GET",
1181
+ redirect: "manual",
1182
+ headers: {
1183
+ Cookie: serializeCookieJar(cookieJar)
1184
+ }
1185
+ });
1186
+ backendStatus = response.status;
1187
+ addSetCookieHeadersToJar(cookieJar, response.headers);
1188
+ const location = response.headers?.get("location") ?? null;
1189
+ const traceRedirect = location ? resolveReadinessRedirect(base, currentUrl, location) : null;
1190
+ const statusAndLocation = traceRedirect && !("error" in traceRedirect) ? `${currentPath} ${response.status} -> ${traceRedirect.path}` : `${currentPath} ${response.status}${location ? " -> [unsafe]" : ""}`;
1191
+ trace.push(statusAndLocation);
1192
+ if (response.status === 200 && currentPath === "/backend") {
1193
+ return {
1194
+ loginStatus: loginResponse.status,
1195
+ backendStatus,
1196
+ healthy: true,
1197
+ detail: `Cookie-backed GET /backend returned 200 (cookies: ${formatCookieNames(cookieJar)})`
1198
+ };
1199
+ }
1200
+ if (response.status < 300 || response.status >= 400) {
1201
+ return {
1202
+ loginStatus: loginResponse.status,
1203
+ backendStatus,
1204
+ healthy: false,
1205
+ detail: `Cookie-backed GET ${currentPath} returned ${response.status} (cookies: ${formatCookieNames(cookieJar)}; trace: ${trace.join(" | ")})`
1206
+ };
1207
+ }
1208
+ const redirect = traceRedirect ?? resolveReadinessRedirect(base, currentUrl, location);
1209
+ if ("error" in redirect) {
1210
+ return {
1211
+ loginStatus: loginResponse.status,
1212
+ backendStatus,
1213
+ healthy: false,
1214
+ detail: `Backend browser auth probe followed unsafe redirect: ${redirect.error} (cookies: ${formatCookieNames(cookieJar)}; trace: ${trace.join(" | ")})`
1215
+ };
1216
+ }
1217
+ if (visitedPaths.has(redirect.path)) {
1218
+ trace.push(redirect.path);
1219
+ return {
1220
+ loginStatus: loginResponse.status,
1221
+ backendStatus,
1222
+ healthy: false,
1223
+ detail: `Backend browser auth probe detected redirect loop: ${trace.join(" | ")} (cookies: ${formatCookieNames(cookieJar)})`
1224
+ };
1225
+ }
1226
+ currentUrl = redirect.url;
1227
+ }
1228
+ return {
1229
+ loginStatus: loginResponse.status,
1230
+ backendStatus,
1231
+ healthy: false,
1232
+ detail: `Backend browser auth probe exceeded ${BACKEND_BROWSER_AUTH_REDIRECT_LIMIT} redirects (cookies: ${formatCookieNames(cookieJar)}; trace: ${trace.join(" | ")})`
1233
+ };
1234
+ } catch (error) {
1235
+ const message = error instanceof Error ? error.message : String(error);
1236
+ return {
1237
+ loginStatus: null,
1238
+ backendStatus: null,
1239
+ healthy: false,
1240
+ detail: `Backend browser auth probe failed: ${message}`
1241
+ };
1242
+ }
1243
+ }
1067
1244
  async function probeApplicationReadiness(baseUrl) {
1068
- const [frontend, backend, authenticated] = await Promise.all([
1245
+ const [frontend, backend, authenticated, backendBrowserAuth] = await Promise.all([
1069
1246
  probeLoginPage(baseUrl),
1070
1247
  probeBackendLoginEndpoint(baseUrl),
1071
- probeAuthenticatedApi(baseUrl)
1248
+ probeAuthenticatedApi(baseUrl),
1249
+ probeBackendBrowserAuth(baseUrl)
1072
1250
  ]);
1073
1251
  return {
1074
- ready: frontend.healthy && backend.healthy && authenticated.healthy,
1252
+ ready: frontend.healthy && backend.healthy && authenticated.healthy && backendBrowserAuth.healthy,
1075
1253
  frontend,
1076
1254
  backend,
1077
- authenticated
1255
+ authenticated,
1256
+ backendBrowserAuth
1078
1257
  };
1079
1258
  }
1080
1259
  async function acquireEphemeralEnvironmentLock(logPrefix) {
@@ -1421,8 +1600,9 @@ async function waitForApplicationReadiness(baseUrl, appProcess, options) {
1421
1600
  const lastFrontendDetail = lastProbe?.frontend.detail ?? "GET /login was never observed";
1422
1601
  const lastBackendDetail = lastProbe?.backend.detail ?? "POST /api/auth/login was never observed";
1423
1602
  const lastAuthenticatedDetail = lastProbe?.authenticated.detail ?? "Authenticated API probe was never observed";
1603
+ const lastBackendBrowserAuthDetail = lastProbe?.backendBrowserAuth.detail ?? "Backend browser auth probe was never observed";
1424
1604
  throw new Error(
1425
- `Application did not become ready within ${options.timeoutMs / 1e3} seconds. Last probe: ${lastFrontendDetail}; ${lastBackendDetail}; ${lastAuthenticatedDetail}`
1605
+ `Application did not become ready within ${options.timeoutMs / 1e3} seconds. Last probe: ${lastFrontendDetail}; ${lastBackendDetail}; ${lastAuthenticatedDetail}; ${lastBackendBrowserAuthDetail}`
1426
1606
  );
1427
1607
  }
1428
1608
  function parseOptions(rawArgs) {