Add opt-in AURA trust-check adapter (integrations/aura)#2026
Add opt-in AURA trust-check adapter (integrations/aura)#2026luisllaver wants to merge 21 commits into
Conversation
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
📝 WalkthroughWalkthroughThis PR adds an opt-in, stdlib-only AURA trust-check adapter that GETs /check?did=... to produce AuraVerdict objects, provides a gating API ( ChangesAURA Trust-Check Adapter
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
integrations/aura/tests/fixtures.py (1)
83-83: ⚡ Quick winReturn a copied fixture payload to avoid shared-state test bleed.
Line 83 returns the same mutable dict instance. If one test mutates it (directly or via
raw), later tests can become order-dependent.Proposed fix
+import copy @@ - return table.get(did, RECORDED["did:aura:ghost-bot"]) + return copy.deepcopy(table.get(did, RECORDED["did:aura:ghost-bot"]))As per coding guidelines, “Always create new objects, never mutate existing ones. Use immutable patterns to prevent hidden side effects and enable safe concurrency”.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@integrations/aura/tests/fixtures.py` at line 83, The helper currently returns the literal dict stored in RECORDED (via table.get(...)) which allows tests to mutate shared state; change the return to return a fresh copy of the fixture (use copy.deepcopy) so callers get an independent object. Ensure you import the copy module and apply copy.deepcopy to the result of table.get(did, RECORDED["did:aura:ghost-bot"]) so both the table-provided value and the default RECORDED entry are cloned before returning.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@integrations/aura/__init__.py`:
- Around line 26-34: The __all__ export list is unsorted and triggers Ruff
RUF022; sort the entries in the __all__ list alphabetically (lexicographically)
so imports like "AuraUntrusted", "AuraVerdict", "DEFAULT_ALLOW",
"DEFAULT_BASE_URL", "aura_verdict", "before_settle", and "require_trust" are in
sorted order; update the __all__ definition (the __all__ variable in this
module) to a sorted sequence of the existing symbols to satisfy the linter.
In `@integrations/aura/adapter.py`:
- Around line 194-195: Tighten the fail-open bypass so it only applies to
transport/unreachable cases: change the condition that currently reads "if
fail_open and v.verdict == 'unknown' and not v.has_history: return v" to also
require the verdict to be an unreachable/transport outage indicator (e.g., check
a field like v.unreachable or v.is_unreachable or a specific verdict value such
as 'unreachable') so genuine "unknown counterparty" outcomes are not allowed
through; then add a regression test that calling
before_settle("did:aura:ghost-bot", fail_open=True, ...) still raises
AuraUntrusted to ensure the change blocks untrusted counterparties.
- Around line 151-153: Validate that caller-provided base_url uses the HTTPS
scheme before building the request URL: parse base_url with
urllib.parse.urlparse and check parsed.scheme == "https" (and reject or raise
ValueError / log and fail if not). Apply this check where base_url is used to
construct url (the code that builds url = f"{base_url.rstrip('/')}/check?" +
urllib.parse.urlencode({"did": did})) and ensure you perform the validation
prior to calling _fetch (and before any urllib.request.urlopen usage). Keep the
error path consistent with existing error handling (raise a clear exception or
return an error) so non-HTTPS inputs are rejected early.
In `@integrations/aura/README.md`:
- Around line 87-89: Update the pytest command in the README: the current
example "python -m pytest aura/tests -q" uses an incorrect path for contributors
running from the repo root; replace it with a repo-root-friendly command such as
"python -m pytest -q" (or the correct relative test package path) so tests run
without a “path not found” error, and ensure the README example is consistent
with how tests are invoked elsewhere in the project.
---
Nitpick comments:
In `@integrations/aura/tests/fixtures.py`:
- Line 83: The helper currently returns the literal dict stored in RECORDED (via
table.get(...)) which allows tests to mutate shared state; change the return to
return a fresh copy of the fixture (use copy.deepcopy) so callers get an
independent object. Ensure you import the copy module and apply copy.deepcopy to
the result of table.get(did, RECORDED["did:aura:ghost-bot"]) so both the
table-provided value and the default RECORDED entry are cloned before returning.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: cfe5b0f5-289c-4c28-9a5c-0a8dc1e77663
📒 Files selected for processing (7)
integrations/aura/README.mdintegrations/aura/THREAT_MODEL.mdintegrations/aura/__init__.pyintegrations/aura/adapter.pyintegrations/aura/tests/__init__.pyintegrations/aura/tests/fixtures.pyintegrations/aura/tests/test_adapter.py
| __all__ = [ | ||
| "aura_verdict", | ||
| "before_settle", | ||
| "require_trust", | ||
| "AuraVerdict", | ||
| "AuraUntrusted", | ||
| "DEFAULT_BASE_URL", | ||
| "DEFAULT_ALLOW", | ||
| ] |
There was a problem hiding this comment.
Sort __all__ to satisfy Ruff (RUF022).
This list is currently unsorted and will trigger lint warnings.
Suggested fix
__all__ = [
- "aura_verdict",
- "before_settle",
- "require_trust",
- "AuraVerdict",
"AuraUntrusted",
- "DEFAULT_BASE_URL",
+ "AuraVerdict",
"DEFAULT_ALLOW",
+ "DEFAULT_BASE_URL",
+ "aura_verdict",
+ "before_settle",
+ "require_trust",
]As per coding guidelines, "Use ruff for linting Python code".
🧰 Tools
🪛 Ruff (0.15.13)
[warning] 26-34: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@integrations/aura/__init__.py` around lines 26 - 34, The __all__ export list
is unsorted and triggers Ruff RUF022; sort the entries in the __all__ list
alphabetically (lexicographically) so imports like "AuraUntrusted",
"AuraVerdict", "DEFAULT_ALLOW", "DEFAULT_BASE_URL", "aura_verdict",
"before_settle", and "require_trust" are in sorted order; update the __all__
definition (the __all__ variable in this module) to a sorted sequence of the
existing symbols to satisfy the linter.
| url = f"{base_url.rstrip('/')}/check?" + urllib.parse.urlencode({"did": did}) | ||
| try: | ||
| body = _fetch(url, timeout) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify current code has urlopen usage but no explicit HTTPS scheme gate.
rg -nP 'def aura_verdict|base_url|urlopen|urlparse|scheme' integrations/aura/adapter.pyRepository: affaan-m/ECC
Length of output: 423
🏁 Script executed:
sed -n '115,160p' integrations/aura/adapter.pyRepository: affaan-m/ECC
Length of output: 1971
🏁 Script executed:
rg -n 'DEFAULT_BASE_URL|DEFAULT_TIMEOUT' integrations/aura/adapter.py | head -20Repository: affaan-m/ECC
Length of output: 344
🏁 Script executed:
rg -n 'aura_verdict\(' integrations/aura/adapter.py | head -10Repository: affaan-m/ECC
Length of output: 288
Validate base_url scheme is HTTPS before constructing network request.
Line 151 constructs a URL from caller-provided base_url without enforcing HTTPS. Since urllib.request.urlopen at line 127 accepts any scheme (http, file, ftp, etc.), a caller could pass a non-HTTPS URL, bypassing security expectations.
Proposed fix
def aura_verdict(
@@
) -> AuraVerdict:
@@
if not did or not str(did).startswith("did:"):
raise ValueError(f"invalid DID: {did!r} (must start with 'did:')")
+ parsed = urllib.parse.urlparse(base_url)
+ if parsed.scheme != "https":
+ raise ValueError(f"invalid base_url scheme: {parsed.scheme!r} (expected 'https')")
url = f"{base_url.rstrip('/')}/check?" + urllib.parse.urlencode({"did": did})Per coding guidelines: "All user inputs must be validated" and "Never trust external data."
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| url = f"{base_url.rstrip('/')}/check?" + urllib.parse.urlencode({"did": did}) | |
| try: | |
| body = _fetch(url, timeout) | |
| if not did or not str(did).startswith("did:"): | |
| raise ValueError(f"invalid DID: {did!r} (must start with 'did:')") | |
| parsed = urllib.parse.urlparse(base_url) | |
| if parsed.scheme != "https": | |
| raise ValueError(f"invalid base_url scheme: {parsed.scheme!r} (expected 'https')") | |
| url = f"{base_url.rstrip('/')}/check?" + urllib.parse.urlencode({"did": did}) | |
| try: | |
| body = _fetch(url, timeout) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@integrations/aura/adapter.py` around lines 151 - 153, Validate that
caller-provided base_url uses the HTTPS scheme before building the request URL:
parse base_url with urllib.parse.urlparse and check parsed.scheme == "https"
(and reject or raise ValueError / log and fail if not). Apply this check where
base_url is used to construct url (the code that builds url =
f"{base_url.rstrip('/')}/check?" + urllib.parse.urlencode({"did": did})) and
ensure you perform the validation prior to calling _fetch (and before any
urllib.request.urlopen usage). Keep the error path consistent with existing
error handling (raise a clear exception or return an error) so non-HTTPS inputs
are rejected early.
| ```bash | ||
| python -m pytest aura/tests -q | ||
| ``` |
There was a problem hiding this comment.
Fix the test command path in docs.
Line 88 likely points to the wrong path for this repo layout; contributors running from repo root may get “path not found”.
Suggested doc fix
-python -m pytest aura/tests -q
+python -m pytest integrations/aura/tests -q📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ```bash | |
| python -m pytest aura/tests -q | |
| ``` |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@integrations/aura/README.md` around lines 87 - 89, Update the pytest command
in the README: the current example "python -m pytest aura/tests -q" uses an
incorrect path for contributors running from the repo root; replace it with a
repo-root-friendly command such as "python -m pytest -q" (or the correct
relative test package path) so tests run without a “path not found” error, and
ensure the README example is consistent with how tests are invoked elsewhere in
the project.
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
4 similar comments
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
There was a problem hiding this comment.
6 issues found across 7 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="integrations/aura/README.md">
<violation number="1" location="integrations/aura/README.md:88">
P2: Incorrect test path in README documentation — `aura/tests` should be `integrations/aura/tests`</violation>
</file>
<file name="integrations/aura/THREAT_MODEL.md">
<violation number="1" location="integrations/aura/THREAT_MODEL.md:32">
P2: Misleading security claim in threat model: adapter docs say MITM is mitigated by 'HTTPS to a pinned host', but `base_url` is fully configurable and the code does not enforce host or certificate pinning.</violation>
</file>
<file name="integrations/aura/tests/fixtures.py">
<violation number="1" location="integrations/aura/tests/fixtures.py:82">
P2: The replay stub only checks the `did` query param, so it won’t fail if the code under test calls the wrong endpoint path.</violation>
</file>
<file name="integrations/aura/adapter.py">
<violation number="1" location="integrations/aura/adapter.py:127">
P1: `base_url` is not validated to use HTTPS, allowing HTTP connections that could be intercepted and tampered with to bypass trust gating.</violation>
<violation number="2" location="integrations/aura/adapter.py:156">
P1: Over-broad `ValueError` exception handling can mask local misconfiguration and, with `fail_open=True`, may silently allow operations that should fail.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| body = _fetch(url, timeout) | ||
| except (urllib.error.URLError, TimeoutError, OSError) as e: | ||
| return AuraVerdict.unreachable(did, f"AURA unreachable: {e}") | ||
| except (json.JSONDecodeError, ValueError) as e: |
There was a problem hiding this comment.
P1: Over-broad ValueError exception handling can mask local misconfiguration and, with fail_open=True, may silently allow operations that should fail.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At integrations/aura/adapter.py, line 156:
<comment>Over-broad `ValueError` exception handling can mask local misconfiguration and, with `fail_open=True`, may silently allow operations that should fail.</comment>
<file context>
@@ -0,0 +1,200 @@
+ body = _fetch(url, timeout)
+ except (urllib.error.URLError, TimeoutError, OSError) as e:
+ return AuraVerdict.unreachable(did, f"AURA unreachable: {e}")
+ except (json.JSONDecodeError, ValueError) as e:
+ return AuraVerdict.unreachable(did, f"AURA returned non-JSON: {e}")
+
</file context>
| except (json.JSONDecodeError, ValueError) as e: | |
| except json.JSONDecodeError as e: |
| # Signature: (url: str, timeout: float) -> dict (raises on transport error) | ||
| def _http_get_json(url: str, timeout: float) -> dict[str, Any]: | ||
| req = urllib.request.Request(url, headers={"User-Agent": "aura-adapter/1.0"}) | ||
| with urllib.request.urlopen(req, timeout=timeout) as resp: # noqa: S310 (https only) |
There was a problem hiding this comment.
P1: base_url is not validated to use HTTPS, allowing HTTP connections that could be intercepted and tampered with to bypass trust gating.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At integrations/aura/adapter.py, line 127:
<comment>`base_url` is not validated to use HTTPS, allowing HTTP connections that could be intercepted and tampered with to bypass trust gating.</comment>
<file context>
@@ -0,0 +1,200 @@
+# Signature: (url: str, timeout: float) -> dict (raises on transport error)
+def _http_get_json(url: str, timeout: float) -> dict[str, Any]:
+ req = urllib.request.Request(url, headers={"User-Agent": "aura-adapter/1.0"})
+ with urllib.request.urlopen(req, timeout=timeout) as resp: # noqa: S310 (https only)
+ return json.loads(resp.read().decode("utf-8"))
+
</file context>
| Offline — every call replays a recorded `/check` body, no network: | ||
|
|
||
| ```bash | ||
| python -m pytest aura/tests -q |
There was a problem hiding this comment.
P2: Incorrect test path in README documentation — aura/tests should be integrations/aura/tests
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At integrations/aura/README.md, line 88:
<comment>Incorrect test path in README documentation — `aura/tests` should be `integrations/aura/tests`</comment>
<file context>
@@ -0,0 +1,105 @@
+Offline — every call replays a recorded `/check` body, no network:
+
+```bash
+python -m pytest aura/tests -q
+```
+
</file context>
| | 1 | **Endpoint unreachable / timeout** | Returns `unknown` (never raises). Gate is fail-closed by default. | Choose `fail_open` deliberately; pick a sane `timeout`. | | ||
| | 2 | **Spoofed DID** — caller claims a DID it doesn't control | Out of scope: adapter checks reputation, not control of the key. | Verify DID control (signature challenge / auth) **before** trusting the verdict. | | ||
| | 3 | **Stale verdict** — score lags very recent bad behavior | Each call is live (no caching here). | If you cache the result, bound the TTL; don't reuse a verdict across sessions. | | ||
| | 4 | **Endpoint MITM / response tampering** | HTTPS to a pinned host (`agent.auraopenprotocol.org`). Verdict strings are validated against a fixed allow-list; unknown values collapse to `unknown`. | Don't point `base_url` at an untrusted mirror. Consider TLS pinning if your runtime supports it. | |
There was a problem hiding this comment.
P2: Misleading security claim in threat model: adapter docs say MITM is mitigated by 'HTTPS to a pinned host', but base_url is fully configurable and the code does not enforce host or certificate pinning.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At integrations/aura/THREAT_MODEL.md, line 32:
<comment>Misleading security claim in threat model: adapter docs say MITM is mitigated by 'HTTPS to a pinned host', but `base_url` is fully configurable and the code does not enforce host or certificate pinning.</comment>
<file context>
@@ -0,0 +1,55 @@
+| 1 | **Endpoint unreachable / timeout** | Returns `unknown` (never raises). Gate is fail-closed by default. | Choose `fail_open` deliberately; pick a sane `timeout`. |
+| 2 | **Spoofed DID** — caller claims a DID it doesn't control | Out of scope: adapter checks reputation, not control of the key. | Verify DID control (signature challenge / auth) **before** trusting the verdict. |
+| 3 | **Stale verdict** — score lags very recent bad behavior | Each call is live (no caching here). | If you cache the result, bound the TTL; don't reuse a verdict across sessions. |
+| 4 | **Endpoint MITM / response tampering** | HTTPS to a pinned host (`agent.auraopenprotocol.org`). Verdict strings are validated against a fixed allow-list; unknown values collapse to `unknown`. | Don't point `base_url` at an untrusted mirror. Consider TLS pinning if your runtime supports it. |
+| 5 | **Score gaming / Sybil** — cheap DIDs farming a `trusted` score | Inherited from AURA's on-chain cost + dispute dimension; not solvable in the adapter. | Weight `dimensions` (e.g. require non-trivial `interactions` / `dispute_history`) for high-value actions rather than trusting the aggregate alone. |
+| 6 | **Over-trust** — using the verdict as sole gate for irreversible value | `new`/`unknown` rejected by default; `dimensions` exposed. | For high-value settlement, combine with action-risk + escrow + manual review. |
</file context>
| | 4 | **Endpoint MITM / response tampering** | HTTPS to a pinned host (`agent.auraopenprotocol.org`). Verdict strings are validated against a fixed allow-list; unknown values collapse to `unknown`. | Don't point `base_url` at an untrusted mirror. Consider TLS pinning if your runtime supports it. | | |
| +| 4 | **Endpoint MITM / response tampering** | HTTPS to the configured host (default `agent.auraopenprotocol.org`). Verdict strings are validated against a fixed allow-list; unknown values collapse to `unknown`. | Don't point `base_url` at an untrusted mirror. Consider TLS pinning if your runtime supports it. | |
| def _fetch(url: str, timeout: float) -> dict[str, Any]: | ||
| from urllib.parse import parse_qs, urlparse | ||
|
|
||
| did = parse_qs(urlparse(url).query).get("did", [""])[0] |
There was a problem hiding this comment.
P2: The replay stub only checks the did query param, so it won’t fail if the code under test calls the wrong endpoint path.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At integrations/aura/tests/fixtures.py, line 82:
<comment>The replay stub only checks the `did` query param, so it won’t fail if the code under test calls the wrong endpoint path.</comment>
<file context>
@@ -0,0 +1,94 @@
+ def _fetch(url: str, timeout: float) -> dict[str, Any]:
+ from urllib.parse import parse_qs, urlparse
+
+ did = parse_qs(urlparse(url).query).get("did", [""])[0]
+ return table.get(did, RECORDED["did:aura:ghost-bot"])
+
</file context>
|
Pushed a small hardening update: |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
integrations/aura/tests/test_adapter.py (1)
116-125: ⚡ Quick winAdd pytest category markers to the new tests.
These tests should be annotated with
@pytest.mark.unitto align with the project's test organization pattern (used intests/test_templates.py,tests/test_claude_provider.py, and others) and follow coding guidelines for pytest marker usage.♻️ Suggested patch
+@pytest.mark.unit def test_fail_open_does_not_pass_reachable_unknown(): # A reachable AURA that returns `unknown` (ghost DID) is still rejected even # with fail_open — fail_open only excuses transport failures. with pytest.raises(AuraUntrusted): before_settle("did:aura:ghost-bot", fail_open=True, _fetch=FETCH) +@pytest.mark.unit def test_reachable_verdict_marked_reachable(): v = aura_verdict("did:aura:ghost-bot", _fetch=FETCH) assert v.reachable is True🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@integrations/aura/tests/test_adapter.py` around lines 116 - 125, Add the pytest unit marker to both new tests by decorating test_fail_open_does_not_pass_reachable_unknown and test_reachable_verdict_marked_reachable with `@pytest.mark.unit`; ensure pytest is imported in integrations/aura/tests/test_adapter.py if it's not already, and place the decorator immediately above each test function definition to match project test organization.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@integrations/aura/tests/test_adapter.py`:
- Around line 116-125: Add the pytest unit marker to both new tests by
decorating test_fail_open_does_not_pass_reachable_unknown and
test_reachable_verdict_marked_reachable with `@pytest.mark.unit`; ensure pytest is
imported in integrations/aura/tests/test_adapter.py if it's not already, and
place the decorator immediately above each test function definition to match
project test organization.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e3a640fe-fba8-4a9f-a2a5-0570e1c5b00e
📒 Files selected for processing (3)
integrations/aura/README.mdintegrations/aura/adapter.pyintegrations/aura/tests/test_adapter.py
✅ Files skipped from review due to trivial changes (1)
- integrations/aura/README.md
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
5 similar comments
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
Opt-in, read-only AURA trust-check adapter, per the boundary agreed in discussion #2003.
What it is — a
integrations/auramodule that lets an ECC agent check a counterparty'sbackward-looking reputation before delegating or settling. External adapter, zero core
coupling, no escrow/wallet signing, fail-closed by default.
API
aura_verdict(did)→ typed{verdict, reason, score, ...}(verdict ∈ trusted|caution|high_risk|new|unknown)before_settle(did)/require_trust(did)→ gate that raisesAuraUntrustedon high_risk + unknownGET /check?did=...(zero-auth). No PII, no keys, nothing stored.Boundary — pure stdlib (no deps). On an unreachable AURA the verdict is
unknownand thedefault gate rejects it (fail-closed); flip
fail_open=Trueto invert. Purely additive: remove themodule and ECC behaves exactly as before.
Tests —
python -m pytest integrations/aura/tests→ 20 offline tests (VCR-style, no network):every verdict class, the gate's allow-list + fail_open, the unreachable path, input validation.
See
integrations/aura/README.md(enable section) andTHREAT_MODEL.md(6 failure modes:spoofed DID, stale verdict, MITM, Sybil, over-trust, unreachable).
Opened as draft for you to route against the partner/integration lane. Happy to adjust the
boundary, naming, or test layout to match ECC conventions.
Summary by cubic
Adds an opt-in, read-only AURA trust-check adapter to gate settlement or delegation on a counterparty’s reputation. One GET to AURA, fail-closed by default, zero deps, and no core coupling.
New Features
integrations/auramodule withaura_verdict,before_settle(require_trustalias), andAuraUntrusted/AuraVerdict; exportsDEFAULT_BASE_URLandDEFAULT_ALLOW.ok,reason,score,dimensions,has_history, andreachable;.as_dict()returns a minimal shape.high_riskandunknown; allowstrusted,caution,new.fail_openonly passesunknownwhen AURA is unreachable; reachableunknownis still rejected. Configurablebase_urlandtimeout.unknown(no exceptions). Pure stdlib. Remove the module to disable.Migration
before_settle(did)at trust boundaries and handleAuraUntrusted.allow=("trusted","caution"); to avoid outage blocking usefail_open=True.Written for commit 02996a1. Summary will update on new commits. Review in cubic
Summary by CodeRabbit
New Features
Documentation
Tests