@postman-cse/onboarding-bootstrap 2.9.8 → 2.9.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action.cjs +142 -10
- package/dist/cli.cjs +142 -10
- package/dist/index.cjs +142 -10
- package/package.json +1 -1
package/dist/action.cjs
CHANGED
|
@@ -258936,6 +258936,87 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
258936
258936
|
const advised = adviseFromHttpError(httpErr, this.adviceContext("workspace repository linking"));
|
|
258937
258937
|
throw advised ?? httpErr;
|
|
258938
258938
|
}
|
|
258939
|
+
async findWorkspaceForRepo(repoUrl, path10 = "/") {
|
|
258940
|
+
const encodedRepo = encodeURIComponent(repoUrl);
|
|
258941
|
+
const encodedPath = encodeURIComponent(path10);
|
|
258942
|
+
const requestPath2 = `/workspaces/filesystem?repo=${encodedRepo}&path=${encodedPath}`;
|
|
258943
|
+
let response;
|
|
258944
|
+
try {
|
|
258945
|
+
response = await this.proxyRequest("workspaces", "GET", requestPath2);
|
|
258946
|
+
} catch (error2) {
|
|
258947
|
+
return {
|
|
258948
|
+
state: "unknown",
|
|
258949
|
+
reason: error2 instanceof Error ? error2.message : String(error2)
|
|
258950
|
+
};
|
|
258951
|
+
}
|
|
258952
|
+
let bodyText;
|
|
258953
|
+
try {
|
|
258954
|
+
bodyText = await response.text();
|
|
258955
|
+
} catch (error2) {
|
|
258956
|
+
return {
|
|
258957
|
+
state: "unknown",
|
|
258958
|
+
reason: error2 instanceof Error ? error2.message : String(error2)
|
|
258959
|
+
};
|
|
258960
|
+
}
|
|
258961
|
+
let parsed = null;
|
|
258962
|
+
if (bodyText.trim()) {
|
|
258963
|
+
try {
|
|
258964
|
+
parsed = JSON.parse(bodyText);
|
|
258965
|
+
} catch (error2) {
|
|
258966
|
+
return {
|
|
258967
|
+
state: "unknown",
|
|
258968
|
+
reason: error2 instanceof Error ? error2.message : String(error2)
|
|
258969
|
+
};
|
|
258970
|
+
}
|
|
258971
|
+
}
|
|
258972
|
+
const wrappedInvisibleWorkspaceIdRaw = parsed?.error?.meta?.workspaceId;
|
|
258973
|
+
const wrappedInvisibleWorkspaceId = typeof wrappedInvisibleWorkspaceIdRaw === "string" ? wrappedInvisibleWorkspaceIdRaw.trim() : "";
|
|
258974
|
+
if (wrappedInvisibleWorkspaceId) {
|
|
258975
|
+
return { state: "linked-invisible", workspaceId: wrappedInvisibleWorkspaceId };
|
|
258976
|
+
}
|
|
258977
|
+
if (response.status === 200) {
|
|
258978
|
+
if (!parsed || !Object.prototype.hasOwnProperty.call(parsed, "data")) {
|
|
258979
|
+
return {
|
|
258980
|
+
state: "unknown",
|
|
258981
|
+
reason: "Filesystem probe returned 200 without a data payload"
|
|
258982
|
+
};
|
|
258983
|
+
}
|
|
258984
|
+
const data = parsed?.data ?? null;
|
|
258985
|
+
if (data == null) {
|
|
258986
|
+
return { state: "free" };
|
|
258987
|
+
}
|
|
258988
|
+
if (typeof data === "object" && !Array.isArray(data)) {
|
|
258989
|
+
const workspace = data;
|
|
258990
|
+
const id = typeof workspace.id === "string" ? workspace.id.trim() : "";
|
|
258991
|
+
if (id) {
|
|
258992
|
+
const name = typeof workspace.name === "string" ? workspace.name : "";
|
|
258993
|
+
return {
|
|
258994
|
+
state: "linked-visible",
|
|
258995
|
+
workspace: { ...workspace, id, name }
|
|
258996
|
+
};
|
|
258997
|
+
}
|
|
258998
|
+
}
|
|
258999
|
+
return {
|
|
259000
|
+
state: "unknown",
|
|
259001
|
+
reason: "Filesystem probe returned 200 with unrecognized workspace payload"
|
|
259002
|
+
};
|
|
259003
|
+
}
|
|
259004
|
+
if (response.status === 403) {
|
|
259005
|
+
const workspaceIdRaw = parsed?.error?.meta?.workspaceId ?? parsed?.meta?.workspaceId;
|
|
259006
|
+
const workspaceId = typeof workspaceIdRaw === "string" ? workspaceIdRaw.trim() : "";
|
|
259007
|
+
if (workspaceId) {
|
|
259008
|
+
return { state: "linked-invisible", workspaceId };
|
|
259009
|
+
}
|
|
259010
|
+
return {
|
|
259011
|
+
state: "unknown",
|
|
259012
|
+
reason: "Filesystem probe returned 403 without error.meta.workspaceId"
|
|
259013
|
+
};
|
|
259014
|
+
}
|
|
259015
|
+
return {
|
|
259016
|
+
state: "unknown",
|
|
259017
|
+
reason: `Filesystem probe returned HTTP ${response.status}`
|
|
259018
|
+
};
|
|
259019
|
+
}
|
|
258939
259020
|
async linkCollectionsToSpecification(specificationId, collections) {
|
|
258940
259021
|
if (collections.length === 0) {
|
|
258941
259022
|
return;
|
|
@@ -261017,6 +261098,13 @@ function normalizeResponseKey(status) {
|
|
|
261017
261098
|
const raw = String(status);
|
|
261018
261099
|
return /^[1-5]xx$/i.test(raw) ? raw.toUpperCase() : raw;
|
|
261019
261100
|
}
|
|
261101
|
+
function responseBodyExpectation(method, status, content) {
|
|
261102
|
+
const normalizedStatus = normalizeResponseKey(status);
|
|
261103
|
+
if (method === "head" || normalizedStatus === "1XX" || /^1[0-9][0-9]$/.test(normalizedStatus) || normalizedStatus === "204" || normalizedStatus === "205" || normalizedStatus === "304") {
|
|
261104
|
+
return "forbidden";
|
|
261105
|
+
}
|
|
261106
|
+
return Object.keys(content).length > 0 ? "declared" : "unknown";
|
|
261107
|
+
}
|
|
261020
261108
|
function collectSecurityApiKeys(root, operation) {
|
|
261021
261109
|
const securitySchemes = asRecord5(asRecord5(root.components)?.securitySchemes);
|
|
261022
261110
|
const requirements = operation.security === void 0 ? asArray2(root.security) : asArray2(operation.security);
|
|
@@ -261447,6 +261535,13 @@ function collectRequestBody(root, operation, version, operationId, warnings) {
|
|
|
261447
261535
|
const body2 = resolveInternalRef(root, operation.requestBody);
|
|
261448
261536
|
if (!body2) return void 0;
|
|
261449
261537
|
const content = asRecord5(body2.content);
|
|
261538
|
+
for (const [contentType2, mediaObject] of Object.entries(content ?? {})) {
|
|
261539
|
+
if (asRecord5(mediaObject)?.schema === void 0) {
|
|
261540
|
+
warnings.push(
|
|
261541
|
+
`CONTRACT_REQUEST_SCHEMA_UNDOCUMENTED: request body ${contentType2} on ${operationId} declares no schema; generated request payload shape is not validated`
|
|
261542
|
+
);
|
|
261543
|
+
}
|
|
261544
|
+
}
|
|
261450
261545
|
const fieldRules = content ? requestBodyFieldRules(root, content, version, operationId, warnings) : void 0;
|
|
261451
261546
|
if (fieldRules) {
|
|
261452
261547
|
for (const [base, rule] of Object.entries(fieldRules)) {
|
|
@@ -262293,9 +262388,22 @@ function buildContractIndex(root) {
|
|
|
262293
262388
|
const linkExpressions = collectLinkExpressions(root, response, `${lowerMethod.toUpperCase()} ${path10}`, responseWarnings, version, linkTargetSchemas);
|
|
262294
262389
|
const responseContext = `${lowerMethod.toUpperCase()} ${path10} status ${status}`;
|
|
262295
262390
|
const content = responseContent(root, version, response, responseContext, responseWarnings);
|
|
262296
|
-
|
|
262391
|
+
const bodyExpectation = responseBodyExpectation(lowerMethod, status, content);
|
|
262392
|
+
if (bodyExpectation === "forbidden" && Object.keys(content).length > 0) {
|
|
262297
262393
|
responseWarnings.add(`CONTRACT_BODYLESS_STATUS_WITH_CONTENT: ${lowerMethod.toUpperCase()} ${path10} declares content for status ${status}, which RFC 9110 forbids on the wire`);
|
|
262298
262394
|
}
|
|
262395
|
+
if (bodyExpectation === "unknown") {
|
|
262396
|
+
responseWarnings.add(
|
|
262397
|
+
`CONTRACT_RESPONSE_BODY_UNDOCUMENTED: ${responseContext} declares no response content; body presence, media type, and shape are not validated`
|
|
262398
|
+
);
|
|
262399
|
+
}
|
|
262400
|
+
for (const [contentType2, mediaObject] of Object.entries(asRecord5(response.content) ?? {})) {
|
|
262401
|
+
if (asRecord5(mediaObject)?.schema === void 0) {
|
|
262402
|
+
responseWarnings.add(
|
|
262403
|
+
`CONTRACT_RESPONSE_SCHEMA_UNDOCUMENTED: response ${contentType2} on ${responseContext} declares no schema; body shape is not validated`
|
|
262404
|
+
);
|
|
262405
|
+
}
|
|
262406
|
+
}
|
|
262299
262407
|
for (const [contentType2, media] of Object.entries(content)) {
|
|
262300
262408
|
const base = contentType2.toLowerCase().split(";")[0]?.trim() ?? "";
|
|
262301
262409
|
const schemaType = asRecord5(media.schema)?.type;
|
|
@@ -262307,7 +262415,7 @@ function buildContractIndex(root) {
|
|
|
262307
262415
|
const writeOnlyProperties = collectResponseWriteOnlyNames(root, response);
|
|
262308
262416
|
contractResponses[normalizeResponseKey(status)] = {
|
|
262309
262417
|
content,
|
|
262310
|
-
|
|
262418
|
+
bodyExpectation,
|
|
262311
262419
|
headers,
|
|
262312
262420
|
...linkExpressions.length > 0 ? { links: linkExpressions } : {},
|
|
262313
262421
|
...writeOnlyProperties.length > 0 ? { writeOnlyProperties } : {}
|
|
@@ -262583,7 +262691,12 @@ function createContractScript(operation, warnings = []) {
|
|
|
262583
262691
|
" return null;",
|
|
262584
262692
|
"}",
|
|
262585
262693
|
'function responseText() { return pm.response.text() || ""; }',
|
|
262586
|
-
'function isBodyless() { return pm.response.code === 204 || pm.response.code === 205 || pm.response.code === 304 || contract.method === "HEAD"; }',
|
|
262694
|
+
'function isBodyless() { return pm.response.code < 200 || pm.response.code === 204 || pm.response.code === 205 || pm.response.code === 304 || contract.method === "HEAD"; }',
|
|
262695
|
+
"function selectedBodyExpectation() {",
|
|
262696
|
+
' if (isBodyless()) return "forbidden";',
|
|
262697
|
+
' if (!selected) return "unknown";',
|
|
262698
|
+
' return selected.value.bodyExpectation || "unknown";',
|
|
262699
|
+
"}",
|
|
262587
262700
|
'function mediaBase(value) { return String(value || "").toLowerCase().split(";")[0].trim(); }',
|
|
262588
262701
|
'function mediaParts(value) { var base = mediaBase(value); var parts = base.split("/"); return { raw: base, type: parts[0] || "", subtype: parts[1] || "" }; }',
|
|
262589
262702
|
'function isJsonSubtype(subtype) { return subtype === "json" || /\\+json$/.test(subtype); }',
|
|
@@ -262623,6 +262736,7 @@ function createContractScript(operation, warnings = []) {
|
|
|
262623
262736
|
" return matches[0];",
|
|
262624
262737
|
"}",
|
|
262625
262738
|
"var selected = selectedResponseContract();",
|
|
262739
|
+
"var bodyExpectation = selectedBodyExpectation();",
|
|
262626
262740
|
...skipped.length > 0 ? [
|
|
262627
262741
|
// A schema schemasafe could not compile is NOT silently ignored: it is
|
|
262628
262742
|
// surfaced here (and as a CONTRACT_SCHEMA_NOT_COMPILED warning at generation
|
|
@@ -262654,10 +262768,8 @@ function createContractScript(operation, warnings = []) {
|
|
|
262654
262768
|
"});",
|
|
262655
262769
|
"pm.test('Response body matches OpenAPI body contract', function () {",
|
|
262656
262770
|
" if (!selected) return;",
|
|
262657
|
-
|
|
262658
|
-
|
|
262659
|
-
' if (Object.keys(content).length === 0) { pm.expect(responseText().trim().length, "OpenAPI response defines no body but response body was not empty").to.equal(0); }',
|
|
262660
|
-
' else { pm.expect(responseText().trim().length, "OpenAPI response defines a body but response body was empty").to.be.above(0); }',
|
|
262771
|
+
' if (bodyExpectation === "forbidden") { pm.expect(responseText().length, "HTTP semantics forbid a response body for " + contract.method + " " + contract.path + " status " + pm.response.code).to.equal(0); return; }',
|
|
262772
|
+
' if (bodyExpectation === "declared") { pm.expect(responseText().length, "OpenAPI response declares content but response body was empty").to.be.above(0); }',
|
|
262661
262773
|
"});",
|
|
262662
262774
|
"pm.test('Content-Type matches OpenAPI response content', function () {",
|
|
262663
262775
|
" if (!selected || isBodyless()) return;",
|
|
@@ -263700,8 +263812,7 @@ function createContractScript(operation, warnings = []) {
|
|
|
263700
263812
|
' if (contract.method === "HEAD" || pm.response.code === 304) return;',
|
|
263701
263813
|
" var actualBytes = unescape(encodeURIComponent(responseText())).length;",
|
|
263702
263814
|
' if (Number(String(raw).trim()) !== actualBytes) pm.expect.fail("Content-Length must equal the response body byte length when Content-Encoding and Transfer-Encoding are absent (RFC 9110 8.6): " + raw + " !== " + actualBytes);',
|
|
263703
|
-
|
|
263704
|
-
' if (mustBeEmpty && Number(String(raw).trim()) !== 0) pm.expect.fail("OpenAPI defines no response body for " + contract.method + " " + contract.path + " status " + pm.response.code + " but Content-Length was " + raw);',
|
|
263815
|
+
' if (bodyExpectation === "forbidden" && Number(String(raw).trim()) !== 0) pm.expect.fail("HTTP semantics forbid a carried response body for " + contract.method + " " + contract.path + " status " + pm.response.code + " but Content-Length was " + raw);',
|
|
263705
263816
|
"});",
|
|
263706
263817
|
"pm.test('RFC SHOULD-level advisories are documented', function () {",
|
|
263707
263818
|
' pm.expect(rfcAdvisories, "SHOULD-level findings (advisory, non-failing): " + rfcAdvisories.join("; ")).to.be.an("array");',
|
|
@@ -312623,7 +312734,28 @@ async function provisionWorkspace(inputs, dependencies, telemetry, outputs, reso
|
|
|
312623
312734
|
}
|
|
312624
312735
|
telemetry.setTeamId(teamId);
|
|
312625
312736
|
const repoUrl = inputs.repoUrl || "";
|
|
312626
|
-
if (
|
|
312737
|
+
if (repoUrl && dependencies.internalIntegration?.findWorkspaceForRepo) {
|
|
312738
|
+
const probe = await dependencies.internalIntegration.findWorkspaceForRepo(repoUrl);
|
|
312739
|
+
if (probe.state === "linked-invisible") {
|
|
312740
|
+
const orgTail = inputs.workspaceTeamId ? " Verify workspace-team-id; if the owner is in another sub-team, ask that sub-team's admin to disconnect it." : "";
|
|
312741
|
+
throw new Error(
|
|
312742
|
+
`REPOSITORY_LINK_CONFLICT_INVISIBLE: Repository ${repoUrl} at path / is linked to workspace ${probe.workspaceId}, but these credentials cannot view it. No Postman assets were changed. Ask its owner or a team admin to disconnect it.${orgTail}`
|
|
312743
|
+
);
|
|
312744
|
+
}
|
|
312745
|
+
if (probe.state === "linked-visible") {
|
|
312746
|
+
workspaceId = probe.workspace.id;
|
|
312747
|
+
workspaceMutationOwned = true;
|
|
312748
|
+
const nameSuffix = probe.workspace.name ? ` ("${probe.workspace.name}")` : "";
|
|
312749
|
+
dependencies.core.info(
|
|
312750
|
+
`Repository ${repoUrl} at path / is already linked to workspace ${probe.workspace.id}${nameSuffix}; adopting it as the canonical workspace.`
|
|
312751
|
+
);
|
|
312752
|
+
} else if (probe.state === "unknown") {
|
|
312753
|
+
dependencies.core.warning(
|
|
312754
|
+
`Repository link preflight could not determine ownership for ${repoUrl}: ${probe.reason}. Continuing with normal workspace selection.`
|
|
312755
|
+
);
|
|
312756
|
+
}
|
|
312757
|
+
}
|
|
312758
|
+
if (!workspaceId && repoUrl && inputs.postmanAccessToken && teamId) {
|
|
312627
312759
|
const selection = await runGroup(
|
|
312628
312760
|
dependencies.core,
|
|
312629
312761
|
"Resolve Canonical Workspace",
|
package/dist/cli.cjs
CHANGED
|
@@ -257254,6 +257254,87 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
257254
257254
|
const advised = adviseFromHttpError(httpErr, this.adviceContext("workspace repository linking"));
|
|
257255
257255
|
throw advised ?? httpErr;
|
|
257256
257256
|
}
|
|
257257
|
+
async findWorkspaceForRepo(repoUrl, path8 = "/") {
|
|
257258
|
+
const encodedRepo = encodeURIComponent(repoUrl);
|
|
257259
|
+
const encodedPath = encodeURIComponent(path8);
|
|
257260
|
+
const requestPath2 = `/workspaces/filesystem?repo=${encodedRepo}&path=${encodedPath}`;
|
|
257261
|
+
let response;
|
|
257262
|
+
try {
|
|
257263
|
+
response = await this.proxyRequest("workspaces", "GET", requestPath2);
|
|
257264
|
+
} catch (error) {
|
|
257265
|
+
return {
|
|
257266
|
+
state: "unknown",
|
|
257267
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
257268
|
+
};
|
|
257269
|
+
}
|
|
257270
|
+
let bodyText;
|
|
257271
|
+
try {
|
|
257272
|
+
bodyText = await response.text();
|
|
257273
|
+
} catch (error) {
|
|
257274
|
+
return {
|
|
257275
|
+
state: "unknown",
|
|
257276
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
257277
|
+
};
|
|
257278
|
+
}
|
|
257279
|
+
let parsed = null;
|
|
257280
|
+
if (bodyText.trim()) {
|
|
257281
|
+
try {
|
|
257282
|
+
parsed = JSON.parse(bodyText);
|
|
257283
|
+
} catch (error) {
|
|
257284
|
+
return {
|
|
257285
|
+
state: "unknown",
|
|
257286
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
257287
|
+
};
|
|
257288
|
+
}
|
|
257289
|
+
}
|
|
257290
|
+
const wrappedInvisibleWorkspaceIdRaw = parsed?.error?.meta?.workspaceId;
|
|
257291
|
+
const wrappedInvisibleWorkspaceId = typeof wrappedInvisibleWorkspaceIdRaw === "string" ? wrappedInvisibleWorkspaceIdRaw.trim() : "";
|
|
257292
|
+
if (wrappedInvisibleWorkspaceId) {
|
|
257293
|
+
return { state: "linked-invisible", workspaceId: wrappedInvisibleWorkspaceId };
|
|
257294
|
+
}
|
|
257295
|
+
if (response.status === 200) {
|
|
257296
|
+
if (!parsed || !Object.prototype.hasOwnProperty.call(parsed, "data")) {
|
|
257297
|
+
return {
|
|
257298
|
+
state: "unknown",
|
|
257299
|
+
reason: "Filesystem probe returned 200 without a data payload"
|
|
257300
|
+
};
|
|
257301
|
+
}
|
|
257302
|
+
const data = parsed?.data ?? null;
|
|
257303
|
+
if (data == null) {
|
|
257304
|
+
return { state: "free" };
|
|
257305
|
+
}
|
|
257306
|
+
if (typeof data === "object" && !Array.isArray(data)) {
|
|
257307
|
+
const workspace = data;
|
|
257308
|
+
const id = typeof workspace.id === "string" ? workspace.id.trim() : "";
|
|
257309
|
+
if (id) {
|
|
257310
|
+
const name = typeof workspace.name === "string" ? workspace.name : "";
|
|
257311
|
+
return {
|
|
257312
|
+
state: "linked-visible",
|
|
257313
|
+
workspace: { ...workspace, id, name }
|
|
257314
|
+
};
|
|
257315
|
+
}
|
|
257316
|
+
}
|
|
257317
|
+
return {
|
|
257318
|
+
state: "unknown",
|
|
257319
|
+
reason: "Filesystem probe returned 200 with unrecognized workspace payload"
|
|
257320
|
+
};
|
|
257321
|
+
}
|
|
257322
|
+
if (response.status === 403) {
|
|
257323
|
+
const workspaceIdRaw = parsed?.error?.meta?.workspaceId ?? parsed?.meta?.workspaceId;
|
|
257324
|
+
const workspaceId = typeof workspaceIdRaw === "string" ? workspaceIdRaw.trim() : "";
|
|
257325
|
+
if (workspaceId) {
|
|
257326
|
+
return { state: "linked-invisible", workspaceId };
|
|
257327
|
+
}
|
|
257328
|
+
return {
|
|
257329
|
+
state: "unknown",
|
|
257330
|
+
reason: "Filesystem probe returned 403 without error.meta.workspaceId"
|
|
257331
|
+
};
|
|
257332
|
+
}
|
|
257333
|
+
return {
|
|
257334
|
+
state: "unknown",
|
|
257335
|
+
reason: `Filesystem probe returned HTTP ${response.status}`
|
|
257336
|
+
};
|
|
257337
|
+
}
|
|
257257
257338
|
async linkCollectionsToSpecification(specificationId, collections) {
|
|
257258
257339
|
if (collections.length === 0) {
|
|
257259
257340
|
return;
|
|
@@ -259335,6 +259416,13 @@ function normalizeResponseKey(status) {
|
|
|
259335
259416
|
const raw = String(status);
|
|
259336
259417
|
return /^[1-5]xx$/i.test(raw) ? raw.toUpperCase() : raw;
|
|
259337
259418
|
}
|
|
259419
|
+
function responseBodyExpectation(method, status, content) {
|
|
259420
|
+
const normalizedStatus = normalizeResponseKey(status);
|
|
259421
|
+
if (method === "head" || normalizedStatus === "1XX" || /^1[0-9][0-9]$/.test(normalizedStatus) || normalizedStatus === "204" || normalizedStatus === "205" || normalizedStatus === "304") {
|
|
259422
|
+
return "forbidden";
|
|
259423
|
+
}
|
|
259424
|
+
return Object.keys(content).length > 0 ? "declared" : "unknown";
|
|
259425
|
+
}
|
|
259338
259426
|
function collectSecurityApiKeys(root, operation) {
|
|
259339
259427
|
const securitySchemes = asRecord5(asRecord5(root.components)?.securitySchemes);
|
|
259340
259428
|
const requirements = operation.security === void 0 ? asArray2(root.security) : asArray2(operation.security);
|
|
@@ -259765,6 +259853,13 @@ function collectRequestBody(root, operation, version, operationId, warnings) {
|
|
|
259765
259853
|
const body2 = resolveInternalRef(root, operation.requestBody);
|
|
259766
259854
|
if (!body2) return void 0;
|
|
259767
259855
|
const content = asRecord5(body2.content);
|
|
259856
|
+
for (const [contentType2, mediaObject] of Object.entries(content ?? {})) {
|
|
259857
|
+
if (asRecord5(mediaObject)?.schema === void 0) {
|
|
259858
|
+
warnings.push(
|
|
259859
|
+
`CONTRACT_REQUEST_SCHEMA_UNDOCUMENTED: request body ${contentType2} on ${operationId} declares no schema; generated request payload shape is not validated`
|
|
259860
|
+
);
|
|
259861
|
+
}
|
|
259862
|
+
}
|
|
259768
259863
|
const fieldRules = content ? requestBodyFieldRules(root, content, version, operationId, warnings) : void 0;
|
|
259769
259864
|
if (fieldRules) {
|
|
259770
259865
|
for (const [base, rule] of Object.entries(fieldRules)) {
|
|
@@ -260611,9 +260706,22 @@ function buildContractIndex(root) {
|
|
|
260611
260706
|
const linkExpressions = collectLinkExpressions(root, response, `${lowerMethod.toUpperCase()} ${path8}`, responseWarnings, version, linkTargetSchemas);
|
|
260612
260707
|
const responseContext = `${lowerMethod.toUpperCase()} ${path8} status ${status}`;
|
|
260613
260708
|
const content = responseContent(root, version, response, responseContext, responseWarnings);
|
|
260614
|
-
|
|
260709
|
+
const bodyExpectation = responseBodyExpectation(lowerMethod, status, content);
|
|
260710
|
+
if (bodyExpectation === "forbidden" && Object.keys(content).length > 0) {
|
|
260615
260711
|
responseWarnings.add(`CONTRACT_BODYLESS_STATUS_WITH_CONTENT: ${lowerMethod.toUpperCase()} ${path8} declares content for status ${status}, which RFC 9110 forbids on the wire`);
|
|
260616
260712
|
}
|
|
260713
|
+
if (bodyExpectation === "unknown") {
|
|
260714
|
+
responseWarnings.add(
|
|
260715
|
+
`CONTRACT_RESPONSE_BODY_UNDOCUMENTED: ${responseContext} declares no response content; body presence, media type, and shape are not validated`
|
|
260716
|
+
);
|
|
260717
|
+
}
|
|
260718
|
+
for (const [contentType2, mediaObject] of Object.entries(asRecord5(response.content) ?? {})) {
|
|
260719
|
+
if (asRecord5(mediaObject)?.schema === void 0) {
|
|
260720
|
+
responseWarnings.add(
|
|
260721
|
+
`CONTRACT_RESPONSE_SCHEMA_UNDOCUMENTED: response ${contentType2} on ${responseContext} declares no schema; body shape is not validated`
|
|
260722
|
+
);
|
|
260723
|
+
}
|
|
260724
|
+
}
|
|
260617
260725
|
for (const [contentType2, media] of Object.entries(content)) {
|
|
260618
260726
|
const base = contentType2.toLowerCase().split(";")[0]?.trim() ?? "";
|
|
260619
260727
|
const schemaType = asRecord5(media.schema)?.type;
|
|
@@ -260625,7 +260733,7 @@ function buildContractIndex(root) {
|
|
|
260625
260733
|
const writeOnlyProperties = collectResponseWriteOnlyNames(root, response);
|
|
260626
260734
|
contractResponses[normalizeResponseKey(status)] = {
|
|
260627
260735
|
content,
|
|
260628
|
-
|
|
260736
|
+
bodyExpectation,
|
|
260629
260737
|
headers,
|
|
260630
260738
|
...linkExpressions.length > 0 ? { links: linkExpressions } : {},
|
|
260631
260739
|
...writeOnlyProperties.length > 0 ? { writeOnlyProperties } : {}
|
|
@@ -260901,7 +261009,12 @@ function createContractScript(operation, warnings = []) {
|
|
|
260901
261009
|
" return null;",
|
|
260902
261010
|
"}",
|
|
260903
261011
|
'function responseText() { return pm.response.text() || ""; }',
|
|
260904
|
-
'function isBodyless() { return pm.response.code === 204 || pm.response.code === 205 || pm.response.code === 304 || contract.method === "HEAD"; }',
|
|
261012
|
+
'function isBodyless() { return pm.response.code < 200 || pm.response.code === 204 || pm.response.code === 205 || pm.response.code === 304 || contract.method === "HEAD"; }',
|
|
261013
|
+
"function selectedBodyExpectation() {",
|
|
261014
|
+
' if (isBodyless()) return "forbidden";',
|
|
261015
|
+
' if (!selected) return "unknown";',
|
|
261016
|
+
' return selected.value.bodyExpectation || "unknown";',
|
|
261017
|
+
"}",
|
|
260905
261018
|
'function mediaBase(value) { return String(value || "").toLowerCase().split(";")[0].trim(); }',
|
|
260906
261019
|
'function mediaParts(value) { var base = mediaBase(value); var parts = base.split("/"); return { raw: base, type: parts[0] || "", subtype: parts[1] || "" }; }',
|
|
260907
261020
|
'function isJsonSubtype(subtype) { return subtype === "json" || /\\+json$/.test(subtype); }',
|
|
@@ -260941,6 +261054,7 @@ function createContractScript(operation, warnings = []) {
|
|
|
260941
261054
|
" return matches[0];",
|
|
260942
261055
|
"}",
|
|
260943
261056
|
"var selected = selectedResponseContract();",
|
|
261057
|
+
"var bodyExpectation = selectedBodyExpectation();",
|
|
260944
261058
|
...skipped.length > 0 ? [
|
|
260945
261059
|
// A schema schemasafe could not compile is NOT silently ignored: it is
|
|
260946
261060
|
// surfaced here (and as a CONTRACT_SCHEMA_NOT_COMPILED warning at generation
|
|
@@ -260972,10 +261086,8 @@ function createContractScript(operation, warnings = []) {
|
|
|
260972
261086
|
"});",
|
|
260973
261087
|
"pm.test('Response body matches OpenAPI body contract', function () {",
|
|
260974
261088
|
" if (!selected) return;",
|
|
260975
|
-
|
|
260976
|
-
|
|
260977
|
-
' if (Object.keys(content).length === 0) { pm.expect(responseText().trim().length, "OpenAPI response defines no body but response body was not empty").to.equal(0); }',
|
|
260978
|
-
' else { pm.expect(responseText().trim().length, "OpenAPI response defines a body but response body was empty").to.be.above(0); }',
|
|
261089
|
+
' if (bodyExpectation === "forbidden") { pm.expect(responseText().length, "HTTP semantics forbid a response body for " + contract.method + " " + contract.path + " status " + pm.response.code).to.equal(0); return; }',
|
|
261090
|
+
' if (bodyExpectation === "declared") { pm.expect(responseText().length, "OpenAPI response declares content but response body was empty").to.be.above(0); }',
|
|
260979
261091
|
"});",
|
|
260980
261092
|
"pm.test('Content-Type matches OpenAPI response content', function () {",
|
|
260981
261093
|
" if (!selected || isBodyless()) return;",
|
|
@@ -262018,8 +262130,7 @@ function createContractScript(operation, warnings = []) {
|
|
|
262018
262130
|
' if (contract.method === "HEAD" || pm.response.code === 304) return;',
|
|
262019
262131
|
" var actualBytes = unescape(encodeURIComponent(responseText())).length;",
|
|
262020
262132
|
' if (Number(String(raw).trim()) !== actualBytes) pm.expect.fail("Content-Length must equal the response body byte length when Content-Encoding and Transfer-Encoding are absent (RFC 9110 8.6): " + raw + " !== " + actualBytes);',
|
|
262021
|
-
|
|
262022
|
-
' if (mustBeEmpty && Number(String(raw).trim()) !== 0) pm.expect.fail("OpenAPI defines no response body for " + contract.method + " " + contract.path + " status " + pm.response.code + " but Content-Length was " + raw);',
|
|
262133
|
+
' if (bodyExpectation === "forbidden" && Number(String(raw).trim()) !== 0) pm.expect.fail("HTTP semantics forbid a carried response body for " + contract.method + " " + contract.path + " status " + pm.response.code + " but Content-Length was " + raw);',
|
|
262023
262134
|
"});",
|
|
262024
262135
|
"pm.test('RFC SHOULD-level advisories are documented', function () {",
|
|
262025
262136
|
' pm.expect(rfcAdvisories, "SHOULD-level findings (advisory, non-failing): " + rfcAdvisories.join("; ")).to.be.an("array");',
|
|
@@ -310849,7 +310960,28 @@ async function provisionWorkspace(inputs, dependencies, telemetry, outputs, reso
|
|
|
310849
310960
|
}
|
|
310850
310961
|
telemetry.setTeamId(teamId);
|
|
310851
310962
|
const repoUrl = inputs.repoUrl || "";
|
|
310852
|
-
if (
|
|
310963
|
+
if (repoUrl && dependencies.internalIntegration?.findWorkspaceForRepo) {
|
|
310964
|
+
const probe = await dependencies.internalIntegration.findWorkspaceForRepo(repoUrl);
|
|
310965
|
+
if (probe.state === "linked-invisible") {
|
|
310966
|
+
const orgTail = inputs.workspaceTeamId ? " Verify workspace-team-id; if the owner is in another sub-team, ask that sub-team's admin to disconnect it." : "";
|
|
310967
|
+
throw new Error(
|
|
310968
|
+
`REPOSITORY_LINK_CONFLICT_INVISIBLE: Repository ${repoUrl} at path / is linked to workspace ${probe.workspaceId}, but these credentials cannot view it. No Postman assets were changed. Ask its owner or a team admin to disconnect it.${orgTail}`
|
|
310969
|
+
);
|
|
310970
|
+
}
|
|
310971
|
+
if (probe.state === "linked-visible") {
|
|
310972
|
+
workspaceId = probe.workspace.id;
|
|
310973
|
+
workspaceMutationOwned = true;
|
|
310974
|
+
const nameSuffix = probe.workspace.name ? ` ("${probe.workspace.name}")` : "";
|
|
310975
|
+
dependencies.core.info(
|
|
310976
|
+
`Repository ${repoUrl} at path / is already linked to workspace ${probe.workspace.id}${nameSuffix}; adopting it as the canonical workspace.`
|
|
310977
|
+
);
|
|
310978
|
+
} else if (probe.state === "unknown") {
|
|
310979
|
+
dependencies.core.warning(
|
|
310980
|
+
`Repository link preflight could not determine ownership for ${repoUrl}: ${probe.reason}. Continuing with normal workspace selection.`
|
|
310981
|
+
);
|
|
310982
|
+
}
|
|
310983
|
+
}
|
|
310984
|
+
if (!workspaceId && repoUrl && inputs.postmanAccessToken && teamId) {
|
|
310853
310985
|
const selection = await runGroup(
|
|
310854
310986
|
dependencies.core,
|
|
310855
310987
|
"Resolve Canonical Workspace",
|
package/dist/index.cjs
CHANGED
|
@@ -258961,6 +258961,87 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
258961
258961
|
const advised = adviseFromHttpError(httpErr, this.adviceContext("workspace repository linking"));
|
|
258962
258962
|
throw advised ?? httpErr;
|
|
258963
258963
|
}
|
|
258964
|
+
async findWorkspaceForRepo(repoUrl, path10 = "/") {
|
|
258965
|
+
const encodedRepo = encodeURIComponent(repoUrl);
|
|
258966
|
+
const encodedPath = encodeURIComponent(path10);
|
|
258967
|
+
const requestPath2 = `/workspaces/filesystem?repo=${encodedRepo}&path=${encodedPath}`;
|
|
258968
|
+
let response;
|
|
258969
|
+
try {
|
|
258970
|
+
response = await this.proxyRequest("workspaces", "GET", requestPath2);
|
|
258971
|
+
} catch (error2) {
|
|
258972
|
+
return {
|
|
258973
|
+
state: "unknown",
|
|
258974
|
+
reason: error2 instanceof Error ? error2.message : String(error2)
|
|
258975
|
+
};
|
|
258976
|
+
}
|
|
258977
|
+
let bodyText;
|
|
258978
|
+
try {
|
|
258979
|
+
bodyText = await response.text();
|
|
258980
|
+
} catch (error2) {
|
|
258981
|
+
return {
|
|
258982
|
+
state: "unknown",
|
|
258983
|
+
reason: error2 instanceof Error ? error2.message : String(error2)
|
|
258984
|
+
};
|
|
258985
|
+
}
|
|
258986
|
+
let parsed = null;
|
|
258987
|
+
if (bodyText.trim()) {
|
|
258988
|
+
try {
|
|
258989
|
+
parsed = JSON.parse(bodyText);
|
|
258990
|
+
} catch (error2) {
|
|
258991
|
+
return {
|
|
258992
|
+
state: "unknown",
|
|
258993
|
+
reason: error2 instanceof Error ? error2.message : String(error2)
|
|
258994
|
+
};
|
|
258995
|
+
}
|
|
258996
|
+
}
|
|
258997
|
+
const wrappedInvisibleWorkspaceIdRaw = parsed?.error?.meta?.workspaceId;
|
|
258998
|
+
const wrappedInvisibleWorkspaceId = typeof wrappedInvisibleWorkspaceIdRaw === "string" ? wrappedInvisibleWorkspaceIdRaw.trim() : "";
|
|
258999
|
+
if (wrappedInvisibleWorkspaceId) {
|
|
259000
|
+
return { state: "linked-invisible", workspaceId: wrappedInvisibleWorkspaceId };
|
|
259001
|
+
}
|
|
259002
|
+
if (response.status === 200) {
|
|
259003
|
+
if (!parsed || !Object.prototype.hasOwnProperty.call(parsed, "data")) {
|
|
259004
|
+
return {
|
|
259005
|
+
state: "unknown",
|
|
259006
|
+
reason: "Filesystem probe returned 200 without a data payload"
|
|
259007
|
+
};
|
|
259008
|
+
}
|
|
259009
|
+
const data = parsed?.data ?? null;
|
|
259010
|
+
if (data == null) {
|
|
259011
|
+
return { state: "free" };
|
|
259012
|
+
}
|
|
259013
|
+
if (typeof data === "object" && !Array.isArray(data)) {
|
|
259014
|
+
const workspace = data;
|
|
259015
|
+
const id = typeof workspace.id === "string" ? workspace.id.trim() : "";
|
|
259016
|
+
if (id) {
|
|
259017
|
+
const name = typeof workspace.name === "string" ? workspace.name : "";
|
|
259018
|
+
return {
|
|
259019
|
+
state: "linked-visible",
|
|
259020
|
+
workspace: { ...workspace, id, name }
|
|
259021
|
+
};
|
|
259022
|
+
}
|
|
259023
|
+
}
|
|
259024
|
+
return {
|
|
259025
|
+
state: "unknown",
|
|
259026
|
+
reason: "Filesystem probe returned 200 with unrecognized workspace payload"
|
|
259027
|
+
};
|
|
259028
|
+
}
|
|
259029
|
+
if (response.status === 403) {
|
|
259030
|
+
const workspaceIdRaw = parsed?.error?.meta?.workspaceId ?? parsed?.meta?.workspaceId;
|
|
259031
|
+
const workspaceId = typeof workspaceIdRaw === "string" ? workspaceIdRaw.trim() : "";
|
|
259032
|
+
if (workspaceId) {
|
|
259033
|
+
return { state: "linked-invisible", workspaceId };
|
|
259034
|
+
}
|
|
259035
|
+
return {
|
|
259036
|
+
state: "unknown",
|
|
259037
|
+
reason: "Filesystem probe returned 403 without error.meta.workspaceId"
|
|
259038
|
+
};
|
|
259039
|
+
}
|
|
259040
|
+
return {
|
|
259041
|
+
state: "unknown",
|
|
259042
|
+
reason: `Filesystem probe returned HTTP ${response.status}`
|
|
259043
|
+
};
|
|
259044
|
+
}
|
|
258964
259045
|
async linkCollectionsToSpecification(specificationId, collections) {
|
|
258965
259046
|
if (collections.length === 0) {
|
|
258966
259047
|
return;
|
|
@@ -261042,6 +261123,13 @@ function normalizeResponseKey(status) {
|
|
|
261042
261123
|
const raw = String(status);
|
|
261043
261124
|
return /^[1-5]xx$/i.test(raw) ? raw.toUpperCase() : raw;
|
|
261044
261125
|
}
|
|
261126
|
+
function responseBodyExpectation(method, status, content) {
|
|
261127
|
+
const normalizedStatus = normalizeResponseKey(status);
|
|
261128
|
+
if (method === "head" || normalizedStatus === "1XX" || /^1[0-9][0-9]$/.test(normalizedStatus) || normalizedStatus === "204" || normalizedStatus === "205" || normalizedStatus === "304") {
|
|
261129
|
+
return "forbidden";
|
|
261130
|
+
}
|
|
261131
|
+
return Object.keys(content).length > 0 ? "declared" : "unknown";
|
|
261132
|
+
}
|
|
261045
261133
|
function collectSecurityApiKeys(root, operation) {
|
|
261046
261134
|
const securitySchemes = asRecord5(asRecord5(root.components)?.securitySchemes);
|
|
261047
261135
|
const requirements = operation.security === void 0 ? asArray2(root.security) : asArray2(operation.security);
|
|
@@ -261472,6 +261560,13 @@ function collectRequestBody(root, operation, version, operationId, warnings) {
|
|
|
261472
261560
|
const body2 = resolveInternalRef(root, operation.requestBody);
|
|
261473
261561
|
if (!body2) return void 0;
|
|
261474
261562
|
const content = asRecord5(body2.content);
|
|
261563
|
+
for (const [contentType2, mediaObject] of Object.entries(content ?? {})) {
|
|
261564
|
+
if (asRecord5(mediaObject)?.schema === void 0) {
|
|
261565
|
+
warnings.push(
|
|
261566
|
+
`CONTRACT_REQUEST_SCHEMA_UNDOCUMENTED: request body ${contentType2} on ${operationId} declares no schema; generated request payload shape is not validated`
|
|
261567
|
+
);
|
|
261568
|
+
}
|
|
261569
|
+
}
|
|
261475
261570
|
const fieldRules = content ? requestBodyFieldRules(root, content, version, operationId, warnings) : void 0;
|
|
261476
261571
|
if (fieldRules) {
|
|
261477
261572
|
for (const [base, rule] of Object.entries(fieldRules)) {
|
|
@@ -262318,9 +262413,22 @@ function buildContractIndex(root) {
|
|
|
262318
262413
|
const linkExpressions = collectLinkExpressions(root, response, `${lowerMethod.toUpperCase()} ${path10}`, responseWarnings, version, linkTargetSchemas);
|
|
262319
262414
|
const responseContext = `${lowerMethod.toUpperCase()} ${path10} status ${status}`;
|
|
262320
262415
|
const content = responseContent(root, version, response, responseContext, responseWarnings);
|
|
262321
|
-
|
|
262416
|
+
const bodyExpectation = responseBodyExpectation(lowerMethod, status, content);
|
|
262417
|
+
if (bodyExpectation === "forbidden" && Object.keys(content).length > 0) {
|
|
262322
262418
|
responseWarnings.add(`CONTRACT_BODYLESS_STATUS_WITH_CONTENT: ${lowerMethod.toUpperCase()} ${path10} declares content for status ${status}, which RFC 9110 forbids on the wire`);
|
|
262323
262419
|
}
|
|
262420
|
+
if (bodyExpectation === "unknown") {
|
|
262421
|
+
responseWarnings.add(
|
|
262422
|
+
`CONTRACT_RESPONSE_BODY_UNDOCUMENTED: ${responseContext} declares no response content; body presence, media type, and shape are not validated`
|
|
262423
|
+
);
|
|
262424
|
+
}
|
|
262425
|
+
for (const [contentType2, mediaObject] of Object.entries(asRecord5(response.content) ?? {})) {
|
|
262426
|
+
if (asRecord5(mediaObject)?.schema === void 0) {
|
|
262427
|
+
responseWarnings.add(
|
|
262428
|
+
`CONTRACT_RESPONSE_SCHEMA_UNDOCUMENTED: response ${contentType2} on ${responseContext} declares no schema; body shape is not validated`
|
|
262429
|
+
);
|
|
262430
|
+
}
|
|
262431
|
+
}
|
|
262324
262432
|
for (const [contentType2, media] of Object.entries(content)) {
|
|
262325
262433
|
const base = contentType2.toLowerCase().split(";")[0]?.trim() ?? "";
|
|
262326
262434
|
const schemaType = asRecord5(media.schema)?.type;
|
|
@@ -262332,7 +262440,7 @@ function buildContractIndex(root) {
|
|
|
262332
262440
|
const writeOnlyProperties = collectResponseWriteOnlyNames(root, response);
|
|
262333
262441
|
contractResponses[normalizeResponseKey(status)] = {
|
|
262334
262442
|
content,
|
|
262335
|
-
|
|
262443
|
+
bodyExpectation,
|
|
262336
262444
|
headers,
|
|
262337
262445
|
...linkExpressions.length > 0 ? { links: linkExpressions } : {},
|
|
262338
262446
|
...writeOnlyProperties.length > 0 ? { writeOnlyProperties } : {}
|
|
@@ -262608,7 +262716,12 @@ function createContractScript(operation, warnings = []) {
|
|
|
262608
262716
|
" return null;",
|
|
262609
262717
|
"}",
|
|
262610
262718
|
'function responseText() { return pm.response.text() || ""; }',
|
|
262611
|
-
'function isBodyless() { return pm.response.code === 204 || pm.response.code === 205 || pm.response.code === 304 || contract.method === "HEAD"; }',
|
|
262719
|
+
'function isBodyless() { return pm.response.code < 200 || pm.response.code === 204 || pm.response.code === 205 || pm.response.code === 304 || contract.method === "HEAD"; }',
|
|
262720
|
+
"function selectedBodyExpectation() {",
|
|
262721
|
+
' if (isBodyless()) return "forbidden";',
|
|
262722
|
+
' if (!selected) return "unknown";',
|
|
262723
|
+
' return selected.value.bodyExpectation || "unknown";',
|
|
262724
|
+
"}",
|
|
262612
262725
|
'function mediaBase(value) { return String(value || "").toLowerCase().split(";")[0].trim(); }',
|
|
262613
262726
|
'function mediaParts(value) { var base = mediaBase(value); var parts = base.split("/"); return { raw: base, type: parts[0] || "", subtype: parts[1] || "" }; }',
|
|
262614
262727
|
'function isJsonSubtype(subtype) { return subtype === "json" || /\\+json$/.test(subtype); }',
|
|
@@ -262648,6 +262761,7 @@ function createContractScript(operation, warnings = []) {
|
|
|
262648
262761
|
" return matches[0];",
|
|
262649
262762
|
"}",
|
|
262650
262763
|
"var selected = selectedResponseContract();",
|
|
262764
|
+
"var bodyExpectation = selectedBodyExpectation();",
|
|
262651
262765
|
...skipped.length > 0 ? [
|
|
262652
262766
|
// A schema schemasafe could not compile is NOT silently ignored: it is
|
|
262653
262767
|
// surfaced here (and as a CONTRACT_SCHEMA_NOT_COMPILED warning at generation
|
|
@@ -262679,10 +262793,8 @@ function createContractScript(operation, warnings = []) {
|
|
|
262679
262793
|
"});",
|
|
262680
262794
|
"pm.test('Response body matches OpenAPI body contract', function () {",
|
|
262681
262795
|
" if (!selected) return;",
|
|
262682
|
-
|
|
262683
|
-
|
|
262684
|
-
' if (Object.keys(content).length === 0) { pm.expect(responseText().trim().length, "OpenAPI response defines no body but response body was not empty").to.equal(0); }',
|
|
262685
|
-
' else { pm.expect(responseText().trim().length, "OpenAPI response defines a body but response body was empty").to.be.above(0); }',
|
|
262796
|
+
' if (bodyExpectation === "forbidden") { pm.expect(responseText().length, "HTTP semantics forbid a response body for " + contract.method + " " + contract.path + " status " + pm.response.code).to.equal(0); return; }',
|
|
262797
|
+
' if (bodyExpectation === "declared") { pm.expect(responseText().length, "OpenAPI response declares content but response body was empty").to.be.above(0); }',
|
|
262686
262798
|
"});",
|
|
262687
262799
|
"pm.test('Content-Type matches OpenAPI response content', function () {",
|
|
262688
262800
|
" if (!selected || isBodyless()) return;",
|
|
@@ -263725,8 +263837,7 @@ function createContractScript(operation, warnings = []) {
|
|
|
263725
263837
|
' if (contract.method === "HEAD" || pm.response.code === 304) return;',
|
|
263726
263838
|
" var actualBytes = unescape(encodeURIComponent(responseText())).length;",
|
|
263727
263839
|
' if (Number(String(raw).trim()) !== actualBytes) pm.expect.fail("Content-Length must equal the response body byte length when Content-Encoding and Transfer-Encoding are absent (RFC 9110 8.6): " + raw + " !== " + actualBytes);',
|
|
263728
|
-
|
|
263729
|
-
' if (mustBeEmpty && Number(String(raw).trim()) !== 0) pm.expect.fail("OpenAPI defines no response body for " + contract.method + " " + contract.path + " status " + pm.response.code + " but Content-Length was " + raw);',
|
|
263840
|
+
' if (bodyExpectation === "forbidden" && Number(String(raw).trim()) !== 0) pm.expect.fail("HTTP semantics forbid a carried response body for " + contract.method + " " + contract.path + " status " + pm.response.code + " but Content-Length was " + raw);',
|
|
263730
263841
|
"});",
|
|
263731
263842
|
"pm.test('RFC SHOULD-level advisories are documented', function () {",
|
|
263732
263843
|
' pm.expect(rfcAdvisories, "SHOULD-level findings (advisory, non-failing): " + rfcAdvisories.join("; ")).to.be.an("array");',
|
|
@@ -312651,7 +312762,28 @@ async function provisionWorkspace(inputs, dependencies, telemetry, outputs, reso
|
|
|
312651
312762
|
}
|
|
312652
312763
|
telemetry.setTeamId(teamId);
|
|
312653
312764
|
const repoUrl = inputs.repoUrl || "";
|
|
312654
|
-
if (
|
|
312765
|
+
if (repoUrl && dependencies.internalIntegration?.findWorkspaceForRepo) {
|
|
312766
|
+
const probe = await dependencies.internalIntegration.findWorkspaceForRepo(repoUrl);
|
|
312767
|
+
if (probe.state === "linked-invisible") {
|
|
312768
|
+
const orgTail = inputs.workspaceTeamId ? " Verify workspace-team-id; if the owner is in another sub-team, ask that sub-team's admin to disconnect it." : "";
|
|
312769
|
+
throw new Error(
|
|
312770
|
+
`REPOSITORY_LINK_CONFLICT_INVISIBLE: Repository ${repoUrl} at path / is linked to workspace ${probe.workspaceId}, but these credentials cannot view it. No Postman assets were changed. Ask its owner or a team admin to disconnect it.${orgTail}`
|
|
312771
|
+
);
|
|
312772
|
+
}
|
|
312773
|
+
if (probe.state === "linked-visible") {
|
|
312774
|
+
workspaceId = probe.workspace.id;
|
|
312775
|
+
workspaceMutationOwned = true;
|
|
312776
|
+
const nameSuffix = probe.workspace.name ? ` ("${probe.workspace.name}")` : "";
|
|
312777
|
+
dependencies.core.info(
|
|
312778
|
+
`Repository ${repoUrl} at path / is already linked to workspace ${probe.workspace.id}${nameSuffix}; adopting it as the canonical workspace.`
|
|
312779
|
+
);
|
|
312780
|
+
} else if (probe.state === "unknown") {
|
|
312781
|
+
dependencies.core.warning(
|
|
312782
|
+
`Repository link preflight could not determine ownership for ${repoUrl}: ${probe.reason}. Continuing with normal workspace selection.`
|
|
312783
|
+
);
|
|
312784
|
+
}
|
|
312785
|
+
}
|
|
312786
|
+
if (!workspaceId && repoUrl && inputs.postmanAccessToken && teamId) {
|
|
312655
312787
|
const selection = await runGroup(
|
|
312656
312788
|
dependencies.core,
|
|
312657
312789
|
"Resolve Canonical Workspace",
|