Skip to content
Merged
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
22 changes: 16 additions & 6 deletions capiscio_sdk/badge.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,11 @@ def from_dict(cls, data: dict) -> "BadgeClaims":
)

def to_dict(self) -> dict:
"""Convert to dictionary."""
"""Convert to dictionary.

Preserves the cnf (confirmation) claim for IAL-1 badges to support
round-trip serialization.
"""
result = {
"jti": self.jti,
"iss": self.issuer,
Expand All @@ -191,18 +195,23 @@ def to_dict(self) -> dict:
"aud": self.audience,
"ial": self.ial,
}
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The to_dict method doesn't preserve the cnf (confirmation) claim from raw_claims for IAL-1 badges. When a BadgeClaims object with cnf is serialized and then deserialized, the cnf claim will be lost. This could break round-trip serialization for IAL-1 badges.

Consider either:

  1. Adding cnf to the output if present in raw_claims
  2. Returning raw_claims directly (if to_dict is meant to serialize back to JWT format)
  3. Documenting that to_dict produces a minimal representation and raw_claims should be used for full JWT claims
Suggested change
}
}
# Preserve cnf claim for IAL-1 / key-bound badges if it was present
if self.raw_claims is not None and "cnf" in self.raw_claims:
result["cnf"] = self.raw_claims["cnf"]

Copilot uses AI. Check for mistakes.
# Preserve cnf claim for IAL-1 / key-bound badges if it was present
if self.raw_claims is not None and "cnf" in self.raw_claims:
result["cnf"] = self.raw_claims["cnf"]
return result

@property
def has_key_binding(self) -> bool:
"""Check if this badge has IAL-1 key binding (cnf claim).
"""Check if this badge has IAL-1 key binding (ial='1' and cnf claim).

Per RFC-002 §7.2.1, IAL-1 badges include a 'cnf' (confirmation) claim
Per RFC-002 §7.2.1, IAL-1 badges MUST include a 'cnf' (confirmation) claim
that cryptographically binds the badge to the agent's private key.
"""
if self.raw_claims is None:
return self.ial == "1"
return "cnf" in self.raw_claims
return (
self.ial == "1"
and self.raw_claims is not None
and "cnf" in self.raw_claims
)

@property
def confirmation_key(self) -> Optional[dict]:
Expand Down Expand Up @@ -515,6 +524,7 @@ async def request_badge(
- 2 (DV): Domain Validated - DNS/HTTP proof
- 3 (OV): Organization Validated - Legal entity
- 4 (EV): Extended Validated - Security audit
Note: LEVEL_0 (Self-Signed) is not available via CA request.
audience: Optional audience restrictions for the badge.
timeout: Request timeout in seconds (not used with gRPC).

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/scoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ def is_production_ready(result: ValidationResult) -> bool:

Command-line usage with `--detailed-scores` flag and JSON output.

[:octicons-arrow-right-24: CLI Usage](https://docs.capisc.io/capiscio-cli/scoring-system/)
[:octicons-arrow-right-24: CLI Usage](https://docs.capisc.io/reference/cli/#validate)
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only change in the entire PR that actually relates to the stated purpose of "CLI naming consolidation from capiscio-cli to capiscio". All other changes in this PR (5 files) are unrelated feature additions including:

  • Adding TrustLevel LEVEL_0 and LEVEL_4
  • Adding IAL (Identity Assurance Level) support
  • Adding key binding properties (has_key_binding, confirmation_key)
  • Adding exclude_paths parameter to FastAPI middleware
  • Removing pytest markers from pyproject.toml

Either the PR description is incorrect and should describe these feature additions, or these unrelated changes should be moved to separate PRs. Mixing unrelated changes makes code review difficult and complicates the git history.

Copilot uses AI. Check for mistakes.

- **📖 Core Concepts**

Expand Down
4 changes: 0 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,6 @@ testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
markers = [
"integration: marks tests as integration tests (require external services)",
"slow: marks tests as slow (deselect with '-m not slow')",
]

[tool.coverage.run]
source = ["capiscio_sdk"]
Expand Down
Loading