You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
adds LHP-v2 contracts for loop registration, sanitized case projections, scope-hashed handoffs, claims, approvals, results, verification, and bounded RT-2 probe plans
adds a signed async coordinator client shared by SOC, NOC, Engineering, Knowledge, and Observatory
adds an optional FastAPI/Postgres coordinator with transactional state, claim leases, replay protection, immutable transition events, and a trace outbox
normalizes the package version to 0.9.0 and commits generated schemas and a lockfile
Why
The existing loops use pair-specific LHP copies and GitHub labels. This provides one neutral, capability-based handoff authority without turning the trace collector or NOC CaseService into the organizational control plane.
Safety
per-loop HMAC identities are scoped server-side
approvals bind the canonical handoff scope hash
the coordinator stores sanitized projections; private loop state remains source-owned
Here are some key observations to aid the review process:
⏱️ Estimated effort to review: 5 🔵🔵🔵🔵🔵
🏅 Score: 85
🧪 PR contains tests
🔒 Security concerns
Sensitive information exposure: The trace outbox in db.py (line 618-634) forwards unsanitized summary fields from handoff events to the collector. These summaries can contain arbitrary text from handoff envelopes, approval rationale, or operation requests, potentially leaking secrets or sensitive data into telemetry. No sanitization is applied before serialization.
The trace outbox (lines 618-634) serializes the full HandoffEvent into the collector payload, including the summary field. This summary is populated from user-provided strings in the handoff envelope (e.g., summary, rationale, result.summary) without sanitization. If a loop embeds secrets, tokens, or raw telemetry data in these fields, they will be forwarded to the collector's trace endpoint, violating the invariant that raw logs, secrets, and live telemetry must not appear in trace records.
The allow_insecure_dev flag (line 115, 196-203) completely bypasses HMAC signature verification when set to True. If this flag is accidentally enabled in production (e.g., via env var HYRULE_COORDINATOR_ALLOW_INSECURE_DEV=true), any actor with network access can impersonate any loop, granting full read/write access to all handoffs, cases, and approvals.
The insertion of HandoffRow and IdempotencyRow can raise IntegrityError due to race conditions (e.g., duplicate handoff_id or idempotency key). Wrap the insertions in a try-except block to catch IntegrityError and raise a ValueError with a descriptive message, preventing unhandled 500 errors.
async def create_handoff(self, envelope: HandoffEnvelope) -> HandoffRecord:
async with self.sessions() as session, session.begin():
existing_id = (
await session.execute(
select(IdempotencyRow.handoff_id).where(
IdempotencyRow.source_loop == envelope.source_loop,
IdempotencyRow.idempotency_key == envelope.idempotency_key,
)
)
).scalar_one_or_none()
if existing_id:
row = await session.get(HandoffRow, existing_id)
if row is None:
raise RuntimeError("idempotency record references a missing handoff")
return self._record(row)
if await session.get(HandoffRow, envelope.handoff_id) is not None:
raise ValueError("handoff_id already exists")
...
- session.add(row)- session.add(- IdempotencyRow(...)- )- ...+ try:+ session.add(row)+ session.add(+ IdempotencyRow(...)+ )+ ...+ except IntegrityError:+ raise ValueError("handoff_id or idempotency key conflict")
return self._record(row)
Suggestion importance[1-10]: 6
__
Why: The suggestion correctly identifies a potential IntegrityError scenario in create_handoff and proposes graceful handling. As an error handling improvement, it prevents unhandled 500 errors and has moderate impact (score ≤8).
Low
Prevent unhandled duplicate case insertion
Inserting a new CaseRow can raise IntegrityError if a concurrent request inserts the same case_id. Catch IntegrityError and raise a ValueError to provide a clear error and avoid a 500 response.
async def put_case(self, projection: CaseProjection) -> CaseProjection:
async with self.sessions() as session, session.begin():
row = await session.get(CaseRow, projection.case_id, with_for_update=True)
if row is not None:
...
else:
- session.add(- CaseRow(...)- )+ try:+ session.add(+ CaseRow(...)+ )+ except IntegrityError:+ raise ValueError("case_id already exists")
return projection
Suggestion importance[1-10]: 6
__
Why: This is a valid error handling improvement for put_case to catch IntegrityError on duplicate case_id insertion. Though with_for_update reduces the race, the addition of explicit handling is prudent and has moderate impact (score ≤8).
Low
Make observed_at required in heartbeat
The observed_at field is critical for heartbeat timeliness and ordering. Without it, the system cannot determine when the heartbeat was sent, which may lead to stale state detection failures. Add observed_at to the required array.
Why: The suggestion is valid as observed_at is important for heartbeat timeliness, but making it required is a design choice that may not be critical for correctness. The PR author may have intentionally left it optional.
Low
Make verified_at required in verification result
The verified_at timestamp is essential for audit trails and ordering of verification results. Omitting it can cause confusion in downstream consumers. Add verified_at to the required fields.
Why: While verified_at is useful for audit trails, the schema already includes it with a default of null. The suggestion is reasonable but not a bug fix; it's a design preference.
Low
Make created_at required in handoff event
The created_at field is necessary for event ordering and time-based queries. Without it, events cannot be reliably sequenced. Add created_at to the required fields.
Why: created_at is important for event ordering, but the schema currently allows it to be omitted. The suggestion is valid but reflects a design decision rather than a critical issue.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Why
The existing loops use pair-specific LHP copies and GitHub labels. This provides one neutral, capability-based handoff authority without turning the trace collector or NOC CaseService into the organizational control plane.
Safety
Validation
uv run ruff check .uv run mypy agent_coreuv run --extra coordinator pytest -q— 75 passed