Repository navigation
fix(shadow-ai): report unavailable identities and correct compatibility claims - #221
Conversation
…ty claims Signed-off-by: devdiv07 <sarvenclothing@gmail.com>
Signed-off-by: Imran Siddique <imran.siddique@opaque.co>
imran-siddique
left a comment
There was a problem hiding this comment.
Matches what #215 settled: strict list methods raise on unusable identity, the report interface carries findings, per-record diagnostics and complete, and missing identity produces no unregistered_agent finding. Since no CI job runs nox -s shadow_ai, I ran it: 60 passed.
Main has moved and marketplace/catalog.json conflicts. Merge main in and run python scripts/generate_marketplace_catalog.py rather than resolving the hunk by hand; that gives 41 integrations and validate_integrations 41/0. I will merge once that is pushed.
…ntity-diagnostic Signed-off-by: devdiv07 <sarvenclothing@gmail.com> # Conflicts: # marketplace/catalog.json
carloshvp
left a comment
There was a problem hiding this comment.
Approved at 761697e6f1a0e59181426b4af3d836e641ed2440 for the scoped #215 correction.
The standalone move removes Shadow AI from the integration index and Marketplace, and the README no longer claims direct cMCP or Agent Manifest compatibility. The scanner reports missing, null, blank, and non-string agent identities separately from findings; strict list methods raise instead of returning an apparently complete result. Valid findings survive in the report, and a literal unknown identity remains distinct from a missing identity.
In an isolated checkout at this head, 60 Shadow AI tests passed. Integration validation passed (41 integrations, 0 failures), as did compatibility validation, generated index/catalog checks, compileall, and git diff --check. Independent controls covered a cMCP-shaped record without agent_id, mixed valid and unavailable records, strict failure, CRLF line locations, and rejection of a cMCP tool catalog as an agent registry.
The current head's only reported check is the failing maintainer-approval gate; no CI job runs the Shadow AI suite. This approval covers the identity diagnostic and corrected compatibility claims. It does not establish a working cMCP adapter or close the broader follow-up in #215.
Refs #215
Breaking change
ShadowAIScanner.scan_records()andShadowAIScanner.scan_audit_log()now raiseIdentityUnavailableErrorwhen any tool-call record has no usableagent_id.Returning a findings list in that situation would look complete while some tool calls were never classified. A caller could not tell "no violations" from "some records could not be checked". Raising makes the incomplete classification impossible to miss.
For records that do carry a usable
agent_id, both methods return the same results as before.Behavior on f6e8c8b for tool-call records without a usable
agent_id:agent_id"unknown": usuallyunregistered_agent, butundeclared_toolor no finding at all if the registry lists"unknown"IdentityUnavailableError""or whitespace-onlyunregistered_agentwith an emptysuggested_manifest_id, butundeclared_toolor no finding if the registry holds the same blank keyIdentityUnavailableErrornull, number, booleanAttributeErrorIdentityUnavailableErrorTypeErrorIdentityUnavailableErrorThis is also documented in the Shadow AI README (now
shadow-ai/README.md) under "Compatibility change".Two interfaces
scan_records_report()andscan_audit_log_report()return aScanReport, for callers that need to inspect partial classification:findings: theDiscoveryEvents for records with a usable identityunavailable: oneIdentityUnavailablediagnostic per unclassifiable tool-call record, located by 0-based list index or 1-based physical JSONL linecomplete: a property derived fromunavailablescan_records()andscan_audit_log()keep their return behavior for valid records and raise on incomplete classification.IdentityUnavailableErroris aValueErrorsubclass. Its.reportis the sameScanReportthe report method would return, so the valid findings and the diagnostics are not lost when it is raised.All four methods share the same classification logic.
A usable identity is a
strthat is not empty or whitespace-only. It is used verbatim: never trimmed, lowercased or converted from another type.IdentityUnavailablecarries a reason code (missing,null,blank,non_string), plus the JSON type name fornon_string. It has noagent_idorsuggested_manifest_id. The diagnostic does not copy the rejectedagent_idinto an identity field, and the exception message does not print its value. Other record fields are preserved as documented.DiscoveryEventis unchanged and is only produced when an identity is available.completemeans no successfully processed tool-call record was unclassifiable because of unavailable identity. It does not certify that the audit source itself is complete. Malformed JSON lines and non-object records still raisejson.JSONDecodeErrorandAttributeErroras before.JSONL line splitting
JSONL lines are now split only on
\n,\r\nand\r. The previousstr.splitlines()also split on characters such as U+2028, which JSON allows unescaped inside strings. With UTF-8 decoding, that broke a valid record in two and raisedjson.JSONDecodeError; I reproduced this on f6e8c8b. A deterministic regression test feeds the decoded text to the scanner. It covers line splitting only, not how a file is decoded on a given platform. JSONL is still read with Python's default text encoding, which is unchanged.Compatibility claims
Removed
tested_against:cmcp-runtime: "0.2.0": the scanner does not accept cMCP v0.2.0 output directly.agent-manifest: "1.0.0": not a released version (PyPI's latest is 0.12.0).No replacement versions were added, because no such test run has been performed.
The README and manifest description now document the inputs the scanner actually supports:
agent_idtimestamp, copied as-is with no normalization or type validationThey no longer describe cMCP output or the cMCP
catalog.jsonas direct inputs.marketplace/catalog.jsonwas regenerated withscripts/generate_marketplace_catalog.py.Maintainer follow-up
Imran added commit eda98c4, moving Shadow AI into the standalone
shadow-ai/directory.The integration manifest and Marketplace listing have been removed. Shadow AI no longer claims working cMCP or Agent Manifest integration. This supersedes the
integration.yamlandmarketplace/catalog.jsonitems under "Compatibility claims" above.The identity-diagnostic implementation remains unchanged: the source and test files are pure renames. The Nox paths and lint configuration have been updated for the new location.
Scope
This PR covers the identity-reporting and compatibility-claim scope agreed in #215. It does not include:
timestamp_utcmapping, which remains separate as agreed.It references #215 rather than closing it; closing the issue is left to the maintainers.
Testing
Original local verification (60fccb0, before the move)
Run locally on Windows. The commands mirror
validate.ymlandlint.yml, and the Shadow AI tests use thenoxshadow_aisession'sPYTHONPATH; nox itself was not run.integrations/shadow-ai/tests: 60 passed on Python 3.12.12 and 3.13, with both the default Windows encoding and-X utf8.scripts/validate_integrations.py: 41 integrations, 0 failures.scripts/validate_compatibility.py: 0 failures.scripts/generate_integration_index.py --checkandscripts/generate_marketplace_catalog.py --check: current.validate.ymltest files all pass.ruff checkwith CI's rule set andgit diff --check: clean.These results are for 60fccb0 and use the old
integrations/shadow-ai/paths. They were not re-run locally after eda98c4.CI on the updated PR (eda98c4)
ruff, which now coversshadow-ai/), Validate integrations, CodeQL, Check documentation links, and the other triggered workflows.gate) reports failure until a maintainer approves the PR.nox -s shadow_ai), so the 60 tests above are local evidence only.