Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions limacharlie/sdk/cloudsec.py
Original file line number Diff line number Diff line change
Expand Up @@ -2334,12 +2334,8 @@ def get_code_sbom(
leaves this API's auth boundary. It is deliberately short-lived;
fetch it promptly and do not store it.
"""
# The key contains a '/', so it is percent-encoded into ONE path
# segment. The gateway accepts either spelling, but encoding is what
# keeps the request unambiguous for anything in between.
quoted = _quote(repo, safe="")
return self._get(
f"code/repos/{quoted}/sbom", _query_pairs(provider=provider))
"code/sbom", _query_pairs(repo=repo, provider=provider))

def download_code_sbom(
self, repo: str, *, provider: str | None = None,
Expand Down
2 changes: 1 addition & 1 deletion limacharlie/sdk/organization.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def get_schema(self, name: str) -> dict[str, Any]:
Returns:
dict: Schema definition.
"""
return self._client.request("GET", f"orgs/{self.oid}/schema/{urlescape(name, safe='')}")
return self._client.request("GET", f"orgs/{self.oid}/schema", query_params={"name": name})

def reset_schemas(self) -> dict[str, Any]:
"""Reset (rebuild) all event schemas for the organization.
Expand Down
18 changes: 6 additions & 12 deletions tests/unit/test_sdk_cloudsec.py
Original file line number Diff line number Diff line change
Expand Up @@ -981,25 +981,19 @@ def test_get_code_status(self, cs, mock_org):
assert url == f"cloudsec/{OID}/code/status"
assert qp is None

def test_get_code_sbom_percent_encodes_the_key(self, cs, mock_org):
"""The repository key holds a '/', which must not become a path split.

Left unencoded it would add a path segment and the route would not
match at all — a 404 with nothing on the client side to explain it.
"""
def test_get_code_sbom_uses_query_selector(self, cs, mock_org):
mock_org.client.request.return_value = {"sbom": None}
cs.get_code_sbom("refractionPOINT/lc-appsec-fixtures")
repo = "org/group/repo+name"
cs.get_code_sbom(repo)
url, qp = _get_call(mock_org)
assert url == (
f"cloudsec/{OID}/code/repos/"
"refractionPOINT%2Flc-appsec-fixtures/sbom")
assert qp is None
assert url == f"cloudsec/{OID}/code/sbom"
assert qp == [("repo", repo)]

def test_get_code_sbom_provider(self, cs, mock_org):
mock_org.client.request.return_value = {"sbom": None}
cs.get_code_sbom("acme/api", provider="github")
_, qp = _get_call(mock_org)
assert qp == [("provider", "github")]
assert qp == [("repo", "acme/api"), ("provider", "github")]

def test_rescan_code_repo_posts_the_trigger(self, cs, mock_org):
mock_org.client.request.return_value = {"accepted": True}
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_sdk_organization.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def test_get_schemas_with_platform(self, org, mock_client):

def test_get_schema(self, org, mock_client):
org.get_schema("NEW_PROCESS")
mock_client.request.assert_called_once_with("GET", "orgs/test-oid-123/schema/NEW_PROCESS")
mock_client.request.assert_called_once_with("GET", "orgs/test-oid-123/schema", query_params={"name": "NEW_PROCESS"})

def test_reset_schemas(self, org, mock_client):
org.reset_schemas()
Expand Down
Loading