fix(ci): classify organization API access denials safely
Deploy EG-BIM QA Gateway / deploy (push) Failing after 54s
Deploy EG-BIM QA Gateway / deploy (push) Failing after 54s
Report documented operation, scope and exposure error codes, permitted exposure enums and proxy challenge indicators during deployment checks. Exclude arbitrary upstream messages and credential material while retaining failure on denied access. Validation: source checks and 123 tests pass. Retried staging run 227194 still returns org_context_http_403; the new diagnostic requires the user-managed push before a further run.
This commit is contained in:
1 parent
bed970a175
commit
e2a6168744
3 files changed
+78
-1
No files matched your search
@@ -114,3 +114,51 @@ test('a partial directory fails and diagnostics point to the forbidden root inst
|
||||
}), /org_context_http_403/);
|
||||
assert.deepEqual(logs.map(line => JSON.parse(line).tenantId), [deniedRoot]);
|
||||
});
|
||||
|
||||
for (const code of ['credential_operation_mismatch', 'credential_scope_exceeded', 'credential_exposure_exceeded']) {
|
||||
test(`access diagnostics preserve the documented ${code} reason while excluding upstream messages`, async () => {
|
||||
const logs = [];
|
||||
await assert.rejects(verifyOrganization(settings(), {
|
||||
fetchImpl: async () => response({ code, message: 'private-server-message', details: {
|
||||
grantedExposure: 'members', requiredExposure: 'identifiers', secret: 'private-value'
|
||||
} }, 403),
|
||||
log: line => logs.push(line)
|
||||
}), /org_context_http_403/);
|
||||
const diagnostic = JSON.parse(logs[0]);
|
||||
assert.equal(diagnostic.upstreamCode, code);
|
||||
assert.equal(diagnostic.grantedExposure, 'members');
|
||||
assert.equal(diagnostic.requiredExposure, 'identifiers');
|
||||
assert.ok(!logs[0].includes('private-server-message'));
|
||||
assert.ok(!logs[0].includes('private-value'));
|
||||
});
|
||||
}
|
||||
|
||||
test('unrecognized codes and invalid enum values cannot expose private upstream strings', async () => {
|
||||
const logs = [];
|
||||
await assert.rejects(verifyOrganization(settings(), {
|
||||
fetchImpl: async () => response({ code: 'private-code', details: {
|
||||
grantedExposure: 'private-granted', requiredExposure: 'private-required'
|
||||
} }, 403),
|
||||
log: line => logs.push(line)
|
||||
}), /org_context_http_403/);
|
||||
const diagnostic = JSON.parse(logs[0]);
|
||||
assert.equal(diagnostic.upstreamCode, 'unrecognized');
|
||||
assert.equal(diagnostic.grantedExposure, undefined);
|
||||
assert.equal(diagnostic.requiredExposure, undefined);
|
||||
assert.ok(!logs[0].includes('private-'));
|
||||
});
|
||||
|
||||
test('HTML proxy challenges are distinguishable without logging HTML or bypassing the failure', async () => {
|
||||
const logs = [];
|
||||
await assert.rejects(verifyOrganization(settings(), {
|
||||
fetchImpl: async () => new Response('<html>private-challenge-body</html>', {
|
||||
status: 403, headers: { 'content-type': 'text/html', 'cf-mitigated': 'challenge' }
|
||||
}),
|
||||
log: line => logs.push(line)
|
||||
}), /org_context_http_403/);
|
||||
const diagnostic = JSON.parse(logs[0]);
|
||||
assert.equal(diagnostic.responseKind, 'html');
|
||||
assert.equal(diagnostic.proxyChallenge, true);
|
||||
assert.equal(diagnostic.upstreamCode, 'unrecognized');
|
||||
assert.ok(!logs[0].includes('private-challenge-body'));
|
||||
});
|
||||
Reference in new issue
Block a user