Skip to content

feat(constation): wire production miner-key dial path end to end#44

Merged
echobt merged 1 commit into
BaseIntelligence:mainfrom
alpha1122x:feat/constation-prod-orchestration
Jul 27, 2026
Merged

feat(constation): wire production miner-key dial path end to end#44
echobt merged 1 commit into
BaseIntelligence:mainfrom
alpha1122x:feat/constation-prod-orchestration

Conversation

@alpha1122x

@alpha1122x alpha1122x commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Production constation path for option-1: miner submits full-power Lium API key + instance_id.
  • BASE custodies the key, verifies the pod (running + executor.miner_hotkey bind), dials sidecar POST /v1/sidecar/attest, continuously re-checks digest triangle (allowlist required == sidecar actual == Lium declared).
  • On success: seal nested constation_bundle → store → worker forwarder attaches for prism production constation_ok (tier ≤ 1).
  • Fixes B1 (verify key never wired into master router) and B2 (BASE issues nonces; prism alone consumes).

Changes

  • ConstationSettings (BASE_CONSTATION__*), fail-closed enabled=False
  • Fail codes + evaluate_digest_triangle, sidecar URL resolver, HTTP sidecar client
  • Allowlist SoT for sealed_manifest_hashes + alembic 0019
  • MinerPodBinding + POST /internal/v1/constation/register_miner_key
  • ProductionConstationOrchestrator (issue → run → seal → put, never consume)
  • Master lifespan wiring + pre-forward hook
  • Surface S1–S8 + scripts/surface_constation.sh
  • Companion: prism-recipe listen mode already merged (v1.0.0 Platform #2)

Test plan

  • ruff check . + ruff format --check .
  • mypy src tests — clean
  • pytest --cov=base --cov-fail-under=802431 passed, coverage 83.73%
  • bash scripts/surface_constation.sh — 10/10
  • Prism package prod constation suite — 60 passed; test_prism_no_tee_absence intact
  • B1 AST guard: router must receive attestation_verify_key
  • B2: post-seal first consume Hit, second already_consumed; orchestrator source has no .consume(

CI

  • Waiting for required checks on this head SHA.

Notes

  • Tamper-evidence only; no TEE-grade claims; Lium is declared config (negative-only corroboration).
  • Continuous digest re-check is required because Lium allows switch-template after verify.
  • Live Lium E2E still needs LIUM_API_KEY in the operator environment (offline path covered).

Summary by CodeRabbit

  • New Features

    • Added optional Constation orchestration for pre-forward attestation and sealed bundle generation.
    • Added three-way digest verification across required, declared, and sidecar digests.
    • Added sidecar attestation support with nonce, phase, timeout, and endpoint handling.
    • Added miner pod binding with encrypted API-key custody and runtime validation.
    • Added sealed manifest hash registration, validation, persistence, and reporting.
    • Added configuration options for enabling and tuning Constation.
  • Bug Fixes

    • Invalid registrations now return clear client errors instead of server failures.
    • Attestation and pod validation now fail closed when required data is missing or inconsistent.

Miner submits a Lium API key plus instance_id; BASE custodies the key,
verifies the pod, dials the sidecar over HTTP, and continuously re-checks
the digest triangle (allowlist required == sidecar actual == Lium declared)
for the whole run. On success it seals a nested constation_bundle, stores
it, and the worker forwarder attaches it for prism production constation_ok.

Also fixes B1 (attestation verify key was never passed into the master
router) and enforces B2 (BASE issues nonces; only prism consumes them).

Includes allowlist sealed_manifest_hashes as SoT, surface S1-S8, and
fail-closed defaults (constation.enabled=False).
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This change adds production Constation support across persistence, digest validation, sidecar attestation, miner pod binding, bundle orchestration, nonce handling, runtime configuration, master wiring, and HTTP/e2e coverage.

Changes

Constation attestation flow

Layer / File(s) Summary
Allowlist and sealed-manifest contracts
alembic/versions/*, src/base/db/models.py, src/base/compute/digest_allowlist.py, src/base/master/constation/allowlist_repository.py, src/base/master/constation/routes.py
Allowlist records and registration APIs now require and persist validated sealed_manifest_hashes.
Digest triangle and sidecar validation
src/base/compute/constation_triangle.py, src/base/compute/constation_sidecar_*.py, src/base/compute/constation_runner.py, src/base/compute/constation_types.py
Runner polling validates required, Lium-declared, and sidecar digests, resolves sidecar endpoints, parses HTTP attestations, and maps failures to typed codes.
Pod binding and encrypted custody
src/base/compute/constation_custody.py, src/base/compute/constation_pod.py, src/base/master/constation/pod_binding.py, src/base/master/constation/routes.py
Miner keys are probed, encrypted, associated with pod instances, and exposed through authenticated registration with fail-closed errors.
Bundle sealing and orchestration
src/base/master/constation/bundle_seal.py, src/base/master/constation/orchestrator.py
Successful runs produce validated Prism-compatible bundles, issue phase nonces without consuming them, and persist sealed results.
Settings, runtime, and forwarding wiring
src/base/config/settings.py, src/base/master/constation/*, src/base/master/worker_reconciliation.py, src/base/cli_app/main.py
Constation settings, custody runtime construction, attestation-key loading, pre-forward orchestration, and master application wiring are added.
Production fixtures and coverage
scripts/*, tests/unit/*, tests/surface/*
Fixtures and tests cover triangle failures, pod binding, sidecar transport, bundle sealing, nonce behavior, HTTP routes, Prism integration, and end-to-end flows.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • BaseIntelligence/base#41: Adds the related production Lium image-attestation wire and sealed-manifest propagation that this change extends.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.91% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main constation end-to-end production miner-key wiring change.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/base/master/constation/allowlist_repository.py (1)

122-152: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Handle legacy empty sealed_manifest_hashes rows in load_allowlist().

Migration 0019 added image_digest_allowlist.sealed_manifest_hashes with server default {}, while DigestRecord rejects empty maps. Any pre-migration allowlist row is reconstructed there without a per-row try/except, so one legacy record aborts the whole allowlist load and breaks /internal/v1/constation/check_allowlist for every allowed digest. Catch this per-row as “fail closed” for that digest only, or add a backfill before this validation goes live.

🤖 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 `@src/base/master/constation/allowlist_repository.py` around lines 122 - 152,
The load_allowlist method must handle legacy rows whose sealed_manifest_hashes
is empty without aborting the entire load. Add per-row handling around
DigestRecord construction and registration so that an invalid legacy digest is
skipped or otherwise fails closed individually, while valid entries and deny
records continue loading normally.
🧹 Nitpick comments (6)
tests/surface/test_constation_production_surface.py (1)

200-234: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate AST-walk guard for build_constation_router wiring across two test files. Both sites independently re-implement the same ~25-line AST parse that asserts every build_constation_router call site passes attestation_verify_key=; a shared helper avoids drift if the guard's requirements evolve (e.g., checking pod_binding= too).

  • tests/surface/test_constation_production_surface.py#L200-L234: extract the AST-walk into a shared helper (e.g. in a test-utils module) and call it from test_b1s_verify_key_wiring_smoke.
  • tests/unit/test_attestation_verify_key_wiring.py#L71-L102: call the same shared helper from test_main_passes_attestation_verify_key_into_build_constation_router instead of duplicating the AST loop.
🤖 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 `@tests/surface/test_constation_production_surface.py` around lines 200 - 234,
Duplicate AST-walk assertions for build_constation_router wiring should be
centralized to prevent drift. Extract the shared AST parsing and
keyword-validation logic into a test utility, then update
tests/surface/test_constation_production_surface.py:200-234 and
tests/unit/test_attestation_verify_key_wiring.py:71-102 to call that helper from
their respective tests instead of maintaining separate loops; preserve
validation that every call passes attestation_verify_key=.
src/base/master/constation/allowlist_repository.py (1)

73-89: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Same reconstruction risk on the rebind-conflict path.

If an existing row has legacy empty sealed_manifest_hashes, building bound here raises ValueError before the actual conflict comparison runs. Callers wrap this in try/except ValueError -> 422 today, so it degrades gracefully, but the resulting 422 detail will describe a sealed_manifest_hashes validation error rather than the real rebind conflict — worth a clearer message or handling once the load_allowlist fix above is in place.

🤖 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 `@src/base/master/constation/allowlist_repository.py` around lines 73 - 89, The
rebind-conflict path reconstructs the existing row through DigestRecord and can
raise validation errors before reporting the actual conflict. Update the
bound-record handling in the method containing this block to normalize legacy
empty sealed_manifest_hashes consistently with load_allowlist, or otherwise
defer that validation until after the digest conflict comparison, so callers
receive the intended rebind-conflict message.
tests/unit/test_constation_sidecar_client.py (1)

97-110: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Loosen-to-tighten: assertion allows two outcomes though source is deterministic.

Source code always maps httpx.TimeoutException to ConstationFailCode.NETWORK_PARTITION (never SIDECAR_ATTEST_FAILED). Asserting result.reason in {...} weakens this test's ability to catch a regression that silently changes the mapping.

✅ Proposed tightened assertion
-    assert result.reason in {
-        ConstationFailCode.SIDECAR_ATTEST_FAILED,
-        ConstationFailCode.NETWORK_PARTITION,
-    }
+    assert result.reason is ConstationFailCode.NETWORK_PARTITION
🤖 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 `@tests/unit/test_constation_sidecar_client.py` around lines 97 - 110, In
test_attest_timeout_maps_to_connection_failure, tighten the result.reason
assertion to require ConstationFailCode.NETWORK_PARTITION specifically. Keep the
timeout setup and SidecarAttestMiss type assertion unchanged.
src/base/compute/constation_runner.py (1)

192-211: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Final per-sample triangle re-evaluation is unreachable/redundant.

_poll_once (271-283) already returns a ConstationVerdict — never a PollSample — whenever evaluate_digest_triangle fails for a given sample. Since result.samples only contains PollSamples that already passed this exact check with the same request.required_digest, this loop can never actually fail; it re-derives an outcome that's already guaranteed. Consider dropping it (or converting to an assert/comment documenting the invariant) to reduce confusion about what this code path is defending against.

🤖 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 `@src/base/compute/constation_runner.py` around lines 192 - 211, The final
per-sample triangle loop in the enclosing verdict computation is redundant
because _poll_once already excludes samples that fail evaluate_digest_triangle.
Remove this re-evaluation and its failure return, or replace it with a concise
invariant assertion/comment while preserving the existing successful result
handling.
src/base/compute/constation_sidecar_client.py (1)

27-32: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

SidecarAttestPhase enum is defined/exported but unused for validation.

Phase validation uses the separate _VALID_PHASES frozenset literal instead of SidecarAttestPhase, leaving two sources of truth for the same three values.

Also applies to: 252-258

🤖 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 `@src/base/compute/constation_sidecar_client.py` around lines 27 - 32, Update
phase validation to reuse the exported SidecarAttestPhase enum rather than the
separate _VALID_PHASES frozenset literal. Remove the duplicate phase-value
source and ensure validation accepts exactly the enum’s START, INTERVAL, and END
values.
src/base/compute/__init__.py (1)

41-56: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Inconsistent re-export surface for sidecar result/phase types.

SidecarAttestResult is re-exported, but the analogous SidecarEndpointResult union alias is not, despite both being declared in their source modules' __all__. SidecarAttestPhase is similarly omitted. If callers are meant to use base.compute as the package surface for these types, add the missing symbols for consistency.

📦 Proposed fix
 from base.compute.constation_sidecar_client import (
     HttpSidecarAttestor,
     SidecarAttestHit,
     SidecarAttestMiss,
+    SidecarAttestPhase,
     SidecarAttestResult,
 )
 from base.compute.constation_sidecar_endpoint import (
     SidecarEndpointHit,
     SidecarEndpointMiss,
     SidecarEndpointMissReason,
+    SidecarEndpointResult,
     resolve_sidecar_base_url,
 )

Also applies to: 170-183

🤖 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 `@src/base/compute/__init__.py` around lines 41 - 56, Update the re-export
imports in the package initializer to include the missing SidecarAttestPhase
from constation_sidecar_client and SidecarEndpointResult from
constation_sidecar_endpoint, alongside the existing sidecar result types. Ensure
both symbols are also listed in the initializer’s public export surface if it
defines one, preserving base.compute as the access point for these aliases.
🤖 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 `@packages/challenges/prism/src/prism_challenge/attestation_routes.py`:
- Around line 323-340: Move allowlist.register(record) into the existing try
block in register_digest so ValueError from digest rebind conflicts is converted
to the same 422 HTTPException as record-construction errors. Preserve the
current successful response and exception chaining behavior.

In `@src/base/compute/constation_sidecar_endpoint.py`:
- Around line 62-91: Address the transport trust boundary in
resolve_sidecar_base_url: either enforce HTTPS for sidecar URLs or document and
enforce that default HTTP traffic is confined to a trusted isolated network,
especially when targeting executor.executor_ip_address through a
public-published port. Preserve the existing host and port resolution behavior
while making the confidentiality and MITM protection guarantee explicit.

In `@src/base/master/constation/custody_keys.py`:
- Around line 152-198: Strengthen the variant validation in the pre-forward hook
before constructing ConstationOrchestrationRequest: require a non-empty string
and validate or coerce it through ImageVariant, catching ValueError and
returning without forwarding when invalid. Replace the current variant is not
None gate while preserving the existing incomplete-identity debug behavior for
missing or invalid variants.

In `@src/base/master/constation/orchestrator.py`:
- Around line 313-336: Update _issue_blocking so durable or awaitable nonce
issuance runs on the already active executor/event loop instead of invoking
_run_coro_in_worker with a newly created loop per poll. Preserve the existing
asyncio.get_running_loop() check and synchronous issuance behavior, and reuse
the established executor-loop scheduling mechanism so the shared session factory
remains on its owning loop.

In `@src/base/master/constation/pod_binding.py`:
- Around line 66-164: Centralize the probe error-classification flow and
nonblank validation used by pod_binding.register with the existing
LiumKeyCustody.register implementation and its _require_nonblank helper. Update
register to call the shared custody logic, remove the duplicated local probe
handling and helper, and preserve the current fail-closed verdicts and
pod-binding behavior.

In `@src/base/master/worker_reconciliation.py`:
- Around line 401-414: Decouple the _constation_hook invocation in _forward from
reconcile_once’s session_scope so attestation work cannot hold the
reconciliation DB transaction open. Schedule the hook only after the transaction
commits, preferably as a background task, while preserving the existing payload,
winner hotkey, exception logging, and forward-success behavior; if post-commit
dispatch is not available, enforce an explicit bounded timeout.

---

Outside diff comments:
In `@src/base/master/constation/allowlist_repository.py`:
- Around line 122-152: The load_allowlist method must handle legacy rows whose
sealed_manifest_hashes is empty without aborting the entire load. Add per-row
handling around DigestRecord construction and registration so that an invalid
legacy digest is skipped or otherwise fails closed individually, while valid
entries and deny records continue loading normally.

---

Nitpick comments:
In `@src/base/compute/__init__.py`:
- Around line 41-56: Update the re-export imports in the package initializer to
include the missing SidecarAttestPhase from constation_sidecar_client and
SidecarEndpointResult from constation_sidecar_endpoint, alongside the existing
sidecar result types. Ensure both symbols are also listed in the initializer’s
public export surface if it defines one, preserving base.compute as the access
point for these aliases.

In `@src/base/compute/constation_runner.py`:
- Around line 192-211: The final per-sample triangle loop in the enclosing
verdict computation is redundant because _poll_once already excludes samples
that fail evaluate_digest_triangle. Remove this re-evaluation and its failure
return, or replace it with a concise invariant assertion/comment while
preserving the existing successful result handling.

In `@src/base/compute/constation_sidecar_client.py`:
- Around line 27-32: Update phase validation to reuse the exported
SidecarAttestPhase enum rather than the separate _VALID_PHASES frozenset
literal. Remove the duplicate phase-value source and ensure validation accepts
exactly the enum’s START, INTERVAL, and END values.

In `@src/base/master/constation/allowlist_repository.py`:
- Around line 73-89: The rebind-conflict path reconstructs the existing row
through DigestRecord and can raise validation errors before reporting the actual
conflict. Update the bound-record handling in the method containing this block
to normalize legacy empty sealed_manifest_hashes consistently with
load_allowlist, or otherwise defer that validation until after the digest
conflict comparison, so callers receive the intended rebind-conflict message.

In `@tests/surface/test_constation_production_surface.py`:
- Around line 200-234: Duplicate AST-walk assertions for build_constation_router
wiring should be centralized to prevent drift. Extract the shared AST parsing
and keyword-validation logic into a test utility, then update
tests/surface/test_constation_production_surface.py:200-234 and
tests/unit/test_attestation_verify_key_wiring.py:71-102 to call that helper from
their respective tests instead of maintaining separate loops; preserve
validation that every call passes attestation_verify_key=.

In `@tests/unit/test_constation_sidecar_client.py`:
- Around line 97-110: In test_attest_timeout_maps_to_connection_failure, tighten
the result.reason assertion to require ConstationFailCode.NETWORK_PARTITION
specifically. Keep the timeout setup and SidecarAttestMiss type assertion
unchanged.
🪄 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 Plus

Run ID: 43dfab1c-1207-488a-a148-d3568831ca5d

📥 Commits

Reviewing files that changed from the base of the PR and between 169eb22 and 7c25b1b.

📒 Files selected for processing (47)
  • alembic/versions/0019_allowlist_sealed_manifest_hashes.py
  • packages/challenges/prism/src/prism_challenge/attestation_routes.py
  • scripts/e2e_lium_attestation.py
  • scripts/prism_lium_attestation_e2e.py
  • scripts/surface_constation.sh
  • src/base/cli_app/main.py
  • src/base/compute/__init__.py
  • src/base/compute/constation_custody.py
  • src/base/compute/constation_pod.py
  • src/base/compute/constation_runner.py
  • src/base/compute/constation_sidecar_client.py
  • src/base/compute/constation_sidecar_endpoint.py
  • src/base/compute/constation_triangle.py
  • src/base/compute/constation_types.py
  • src/base/compute/digest_allowlist.py
  • src/base/config/settings.py
  • src/base/db/models.py
  • src/base/master/constation/__init__.py
  • src/base/master/constation/allowlist_repository.py
  • src/base/master/constation/attestation_keys.py
  • src/base/master/constation/bundle_seal.py
  • src/base/master/constation/custody_keys.py
  • src/base/master/constation/orchestrator.py
  • src/base/master/constation/pod_binding.py
  • src/base/master/constation/routes.py
  • src/base/master/worker_reconciliation.py
  • tests/__init__.py
  • tests/surface/__init__.py
  • tests/surface/constation_surface_helpers.py
  • tests/surface/test_constation_production_surface.py
  • tests/surface/test_constation_production_surface_prism_http.py
  • tests/unit/test_attestation_http.py
  • tests/unit/test_attestation_verify_key_wiring.py
  • tests/unit/test_compute_constation_service.py
  • tests/unit/test_compute_digest_allowlist.py
  • tests/unit/test_constation_bundle_seal.py
  • tests/unit/test_constation_main_wiring.py
  • tests/unit/test_constation_orchestrator.py
  • tests/unit/test_constation_pod.py
  • tests/unit/test_constation_pod_binding.py
  • tests/unit/test_constation_settings.py
  • tests/unit/test_constation_sidecar_client.py
  • tests/unit/test_constation_sidecar_endpoint.py
  • tests/unit/test_constation_triangle.py
  • tests/unit/test_digest_allowlist_repository.py
  • tests/unit/test_e2e_lium_attestation_offline.py
  • tests/unit/test_validator_challenge_adapters.py

Comment on lines 323 to 340
async def register_digest(request: Request, body: RegisterDigestBody) -> dict[str, str]:
ensure_default_constation_services(request.app)
allowlist: DigestAllowlist = request.app.state.digest_allowlist
record = DigestRecord(
commit_sha=body.commit_sha,
tree_sha=body.tree_sha,
variant=ImageVariant(body.variant.strip().lower()),
digest=body.digest,
)
try:
record = DigestRecord(
commit_sha=body.commit_sha,
tree_sha=body.tree_sha,
variant=ImageVariant(body.variant.strip().lower()),
digest=body.digest,
sealed_manifest_hashes=body.sealed_manifest_hashes,
)
except ValueError as exc:
raise HTTPException(
status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=str(exc),
) from exc
allowlist.register(record)
return {"status": "registered", "digest": record.digest}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

allowlist.register(record) sits outside the ValueError handler — rebind conflicts 500 instead of 422.

DigestAllowlist.register() raises ValueError when the same digest is rebound to a different commit/tree/variant. Here that call (line 339) is outside the try/except ValueError block, so a legitimate conflict crashes with an unhandled 500. The equivalent endpoint in src/base/master/constation/routes.py correctly wraps both the DigestRecord construction and the allowlist_repo.register(record) call in the same try block, converting ValueError to a 422 — this file should match that pattern.

🐛 Proposed fix to catch registration conflicts too
         try:
             record = DigestRecord(
                 commit_sha=body.commit_sha,
                 tree_sha=body.tree_sha,
                 variant=ImageVariant(body.variant.strip().lower()),
                 digest=body.digest,
                 sealed_manifest_hashes=body.sealed_manifest_hashes,
             )
+            allowlist.register(record)
         except ValueError as exc:
             raise HTTPException(
                 status.HTTP_422_UNPROCESSABLE_ENTITY,
                 detail=str(exc),
             ) from exc
-        allowlist.register(record)
         return {"status": "registered", "digest": record.digest}
📝 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.

Suggested change
async def register_digest(request: Request, body: RegisterDigestBody) -> dict[str, str]:
ensure_default_constation_services(request.app)
allowlist: DigestAllowlist = request.app.state.digest_allowlist
record = DigestRecord(
commit_sha=body.commit_sha,
tree_sha=body.tree_sha,
variant=ImageVariant(body.variant.strip().lower()),
digest=body.digest,
)
try:
record = DigestRecord(
commit_sha=body.commit_sha,
tree_sha=body.tree_sha,
variant=ImageVariant(body.variant.strip().lower()),
digest=body.digest,
sealed_manifest_hashes=body.sealed_manifest_hashes,
)
except ValueError as exc:
raise HTTPException(
status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=str(exc),
) from exc
allowlist.register(record)
return {"status": "registered", "digest": record.digest}
async def register_digest(request: Request, body: RegisterDigestBody) -> dict[str, str]:
ensure_default_constation_services(request.app)
allowlist: DigestAllowlist = request.app.state.digest_allowlist
try:
record = DigestRecord(
commit_sha=body.commit_sha,
tree_sha=body.tree_sha,
variant=ImageVariant(body.variant.strip().lower()),
digest=body.digest,
sealed_manifest_hashes=body.sealed_manifest_hashes,
)
allowlist.register(record)
except ValueError as exc:
raise HTTPException(
status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=str(exc),
) from exc
return {"status": "registered", "digest": record.digest}
🤖 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 `@packages/challenges/prism/src/prism_challenge/attestation_routes.py` around
lines 323 - 340, Move allowlist.register(record) into the existing try block in
register_digest so ValueError from digest rebind conflicts is converted to the
same 422 HTTPException as record-construction errors. Preserve the current
successful response and exception chaining behavior.

Comment on lines +62 to +91
def resolve_sidecar_base_url(
pod_raw: Mapping[str, Any],
*,
internal_port: int,
scheme: str = "http",
) -> SidecarEndpointResult:
"""Resolve ``{scheme}://{host}:{external_port}`` for the sidecar.

Parameters
----------
pod_raw:
Raw Lium ``PodDetailResponse`` mapping (e.g. ``LiumPodRead.raw``).
internal_port:
Container-internal sidecar listen port to look up in ``ports_mapping``.
scheme:
URL scheme; defaults to ``http``.
"""
host = _extract_host(pod_raw)
if host is None:
return SidecarEndpointMiss(SidecarEndpointMissReason.POD_ENDPOINT_MISSING)

mapping_result = _normalize_ports_mapping(pod_raw.get("ports_mapping"))
if isinstance(mapping_result, SidecarEndpointMissReason):
return SidecarEndpointMiss(mapping_result)

external = _lookup_external_port(mapping_result, internal_port)
if external is None:
return SidecarEndpointMiss(SidecarEndpointMissReason.SIDECAR_PORT_UNPUBLISHED)

return SidecarEndpointHit(base_url=f"{scheme}://{_format_host(host)}:{external}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether callers ever override scheme to https, and whether network policy docs mention this.
rg -n 'resolve_sidecar_base_url\(' -A3 -B3
rg -n 'scheme\s*=' src/base/compute/constation_sidecar_endpoint.py src/base/master/constation

Repository: BaseIntelligence/base

Length of output: 159


🏁 Script executed:

#!/bin/bash
set -u

echo "Files matching constation_sidecar_endpoint.py or sidecar/client/constation:"
git ls-files | rg 'constation.*(sidecar|client)$|sidecar.*endpoint|sidecar.*client|constation_sidecar' || true

echo
echo "Search resolve_sidecar_base_url usages:"
rg -n 'resolve_sidecar_base_url' . || true

echo
echo "Search HttpSidecarAttestor / sidecar attestor / sidecar_base_url:"
rg -n 'HttpSidecarAttestor|sidecar.*attest|sidecar_base_url|base_url' . || true

echo
echo "Search scheme occurrences under relevant paths if present:"
rg -n 'scheme\s*=|sidecar.*https|https' src test tests .github README.md 2>/dev/null || true

Repository: BaseIntelligence/base

Length of output: 50378


🏁 Script executed:

#!/bin/bash
set -u

echo "Candidate files:"
git ls-files | rg -i 'constation|sidecar|attest' || true

echo
echo "Top-level source tree snippets around constation:"
for f in $(git ls-files | rg -i 'constation.*sidecar.*endpoint|constation.*sidecar.*client|constation.*sidecar'); do
  echo "--- $f"
  wc -l "$f"
  ast-grep outline "$f" --view compact 2>/dev/null || true
done

Repository: BaseIntelligence/base

Length of output: 3929


🏁 Script executed:

#!/bin/bash
set -u

echo "--- src/base/compute/constation_sidecar_endpoint.py lines 1-120"
sed -n '1,120p' src/base/compute/constation_sidecar_endpoint.py

echo
echo "--- src/base/compute/constation_sidecar_endpoint.py lines 160-200"
sed -n '160,200p' src/base/compute/constation_sidecar_endpoint.py

echo
echo "--- src/base/compute/constation_runner.py lines 300-380"
sed -n '300,380p' src/base/compute/constation_runner.py

echo
echo "--- src/base/compute/constation_sidecar_client.py lines 1-145"
sed -n '1,145p' src/base/compute/constation_sidecar_client.py

echo
echo "--- focused docs/comments for sidecar/constation private network/HTTP"
rg -n -C 2 'sidecar|constation|Lium|Private|private|overlay|HTTP|http|HTTPS|HTTPS|TLS|tls|plaintext|eavesdrop|MITM|in-flight' README.md deploy scripts packages docs src tests/surface tests/unit/test_e2e_lium_attestation_offline.py scripts/e2e_lium_attestation.py scripts/prism_lium_attestation_e2e.py 2>/dev/null | head -n 240

Repository: BaseIntelligence/base

Length of output: 29873


Document or enforce the trust boundary for sidecar HTTP attestation.

resolve_sidecar_base_url always produces http:// unless the caller overrides scheme, and the actual callers use the default against executor.executor_ip_address. If this dial-out uses a public-published sidecar port, it is plaintext on the wire; the HMAC covers payload integrity, not transport confidentiality or MITM resistance. Add an explicit design note, traffic-isolation guarantee, or switch to HTTPS for transport protection.

🤖 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 `@src/base/compute/constation_sidecar_endpoint.py` around lines 62 - 91,
Address the transport trust boundary in resolve_sidecar_base_url: either enforce
HTTPS for sidecar URLs or document and enforce that default HTTP traffic is
confined to a trusted isolated network, especially when targeting
executor.executor_ip_address through a public-published port. Preserve the
existing host and port resolution behavior while making the confidentiality and
MITM protection guarantee explicit.

Comment on lines +152 to +198
md = dict(metadata or {})
required_digest = md.get("required_digest") or md.get("digest")
commit_sha = md.get("commit_sha")
tree_sha = md.get("tree_sha")
variant = md.get("variant")
sealed = md.get("sealed_manifest_hashes")
if not (
isinstance(required_digest, str)
and required_digest
and isinstance(commit_sha, str)
and commit_sha
and isinstance(tree_sha, str)
and tree_sha
and variant is not None
and isinstance(sealed, Mapping)
and sealed
):
logger.debug(
"constation pre-forward hook skipped: incomplete identity "
"on work_unit_id=%s miner_hotkey=%s",
work_unit_id,
miner_hotkey,
)
return
try:
await orchestrator.run(
ConstationOrchestrationRequest(
work_unit_id=work_unit_id,
miner_hotkey=miner_hotkey,
required_digest=required_digest,
commit_sha=commit_sha,
tree_sha=tree_sha,
variant=variant,
sealed_manifest_hashes=dict(sealed),
duration_seconds=float(
md.get("duration_seconds", duration_seconds)
),
pod_id=md.get("pod_id")
if isinstance(md.get("pod_id"), str)
else None,
instance_id=(
md.get("instance_id")
if isinstance(md.get("instance_id"), str)
else None
),
)
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm the declared type of `variant` on ConstationOrchestrationRequest and whether
# str values are coerced to ImageVariant anywhere before use.
rg -n -A5 'class ConstationOrchestrationRequest' src/base/master/constation/orchestrator.py
rg -n 'variant' src/base/master/constation/orchestrator.py
rg -n 'class ImageVariant' src/base/compute/digest_allowlist.py

Repository: BaseIntelligence/base

Length of output: 675


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "custody_keys pre-forward section:"
sed -n '130,210p' src/base/master/constation/custody_keys.py

echo
echo "orchestrator request handling and ImageVariant enum:"
sed -n '1,90p' src/base/compute/digest_allowlist.py
sed -n '45,225p' src/base/master/constation/orchestrator.py

echo
echo "surface helper request usage:"
rg -n -A8 -B5 'orchestration_request|ConstationOrchestrationRequest|ImageVariant' tests/surface/constation_surface_helpers.py

Repository: BaseIntelligence/base

Length of output: 13971


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "ConstationRunner.build_bundle and digest lookup usages:"
rg -n -A12 -B8 'async def build_bundle|class ConstationRunner|sealed_manifest_hashes|variant_mismatch|constation_ok|DigestRecord' src base tests | sed -n '1,260p'

echo
echo "all direct ConstationOrchestrationRequest construction sites:"
rg -n -A6 -B6 'ConstationOrchestrationRequest\(' src tests

Repository: BaseIntelligence/base

Length of output: 18584


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "ConstationRunner build_bundle / seal fields:"
sed -n '95,175p' src/base/compute/constation_runner.py

echo
echo "DigestRecord and allowlist lookup implementations:"
rg -n -A40 'class DigestRecord|def _require_variant|def .*_commit.*|def .*variant|constation_ok|lookup' src/base/compute/digest_allowlist.py tests | sed -n '1,260p'

echo
echo "_require_variant exact behavior:"
python3 - <<'PY'
import ast
from pathlib import Path
path = Path("src/base/compute/digest_allowlist.py")
tree = ast.parse(path.read_text())
for node in ast.walk(tree):
    if isinstance(node, ast.FunctionDef) and node.name == "_require_variant":
        print(ast.get_source_segment(path.read_text(), node))
PY

Repository: BaseIntelligence/base

Length of output: 23742


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "ProductionConstationOrchestrator bundle sealing failure path:"
sed -n '180,260p' src/base/master/constation/orchestrator.py

echo
echo "digest_allowlist.py file-level exact lines of _require_variant and lookup comparison:"
sed -n '82,91p' src/base/compute/digest_allowlist.py
sed -n '215,254p' src/base/compute/digest_allowlist.py

echo
echo "behavioral probe matching the repo variant coercion:"
python3 - <<'PY'
from enum import StrEnum

class ImageVariant(StrEnum):
    CPU = "cpu"
    CUDA = "cuda"

def require_variant(value):
    if isinstance(value, ImageVariant):
        return value
    try:
        return ImageVariant(str(value).strip().lower())
    except ValueError as exc:
        raise ValueError(f"variant must be one of {[v.value for v in ImageVariant]}, got {value!r}") from exc

for value in ["".strip(), "cpu", "  CuDa  ", None, {"kind": "cuda"}]:
    try:
        print(repr(value), "=>", require_variant(value))
    except Exception as exc:
        print(repr(value), "=> raises", type(exc).__name__, str(exc))
PY

Repository: BaseIntelligence/base

Length of output: 5618


Fail closed on invalid variant before forwarding.

variant is not None is weaker than the checks for sibling identity fields and weaker than ImageVariant.__init__ expectations. An empty string or an invalid type/value passes this gate and causes a ValueError during DigestRecord construction, which the orchestrator treats as RUN_INCOMPLETE rather than a missing variant identity. Require a non-empty string that can be coerced to ImageVariant here, or convert it here and fail-closed on ValueError.

🤖 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 `@src/base/master/constation/custody_keys.py` around lines 152 - 198,
Strengthen the variant validation in the pre-forward hook before constructing
ConstationOrchestrationRequest: require a non-empty string and validate or
coerce it through ImageVariant, catching ValueError and returning without
forwarding when invalid. Replace the current variant is not None gate while
preserving the existing incomplete-identity debug behavior for missing or
invalid variants.

Comment on lines +313 to +336
def _issue_blocking(nonce_service: NonceIssuer, binding: NonceBinding) -> NonceRecord:
"""Call ``issue`` from a sync context (runner poll_nonce_fn)."""
issue = nonce_service.issue
# Coroutine function (DurableAttestationNonceService.issue)
if inspect.iscoroutinefunction(issue):
return _run_coro_in_worker(issue(binding))
record = issue(binding)
if inspect.isawaitable(record):
return _run_coro_in_worker(record)
return record


def _run_coro_in_worker(coro: Awaitable[NonceRecord]) -> NonceRecord:
"""Run ``coro`` on a fresh loop in a worker thread (no same-loop deadlock)."""
import concurrent.futures

async def _await_once() -> NonceRecord:
return await coro

def _thread_main() -> NonceRecord:
return asyncio.run(_await_once())

with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
return pool.submit(_thread_main).result(timeout=60.0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect DurableAttestationNonceService.issue to check for event-loop-bound resources
# (DB pools/engines, asyncio.Lock, etc.) created outside the per-call scope.
rg -n "class DurableAttestationNonceService" -A 80 src/base/compute/attestation_nonce.py

Repository: BaseIntelligence/base

Length of output: 159


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Find orchestrator and nonce-related files:"
fd -a 'orchestrator|attestation_nonce|nonce|constation' . | sed 's#^\./##' | head -100

echo
echo "Search relevant symbols:"
rg -n "DurableAttestationNonceService|NonceBinding|NonceRecord|NonceIssuer|poll_nonce_fn|_issue_blocking|_run_coro_in_worker" -S .

Repository: BaseIntelligence/base

Length of output: 16025


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "orchestrator relevant sections:"
sed -n '1,380p' src/base/master/constation/orchestrator.py | cat -n

echo
echo "DurableAttestationNonceService source:"
sed -n '1,170p' src/base/master/constation/nonce_repository.py | cat -n

echo
echo "runners/poll paths:"
sed -n '240,370p' src/base/compute/constation_runner.py | cat -n

Repository: BaseIntelligence/base

Length of output: 27041


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Find session_scope/session_factory definitions and usages:"
fd -a 'session.py|database|factory|engine' src/base | sed 's#^\./##' | head -100

rg -n "async_sessionmaker|create_async_engine|def session_scope|async def session_scope|session_scope_fn|DurableAttestationNonceService\\(" src/base src -S

python3 - <<'PY'
from pathlib import Path
for path in Path("src/base").rglob("*.py"):
    text = path.read_text(errors="ignore")
    if "DurableAttestationNonceService" in text or "async_sessionmaker" in text or "session_scope" in text:
        print(path)
        for i, line in enumerate(text.splitlines(), 1):
            if any(s in line for s in ["DurableAttestationNonceService", "async_sessionmaker", "session_scope", "create_async_engine"]):
                print(f"{i}: {line}")
PY

Repository: BaseIntelligence/base

Length of output: 21076


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "src/base/db/session.py:"
sed -n '1,90p' src/base/db/session.py | cat -n

echo
echo "DurableAttestationNonceService wiring around CLI:"
sed -n '1140,1175p' src/base/cli_app/main.py | cat -n

echo
echo "Search DurableAttestationNonceService construction beyond CLI:"
rg -n "DurableAttestationNonceService\\(" src tests packages 2>/dev/null | sed -n '1,120p'

echo
echo "Search production config/dependency injection for constation nonce service:"
rg -n "constation.*nonce|nonce.*constation|DurableAttestationNonceService|async_sessionmaker|make_session_factory|session_factory" -S src base packages 2>/dev/null | sed -n '1,160p'

Repository: BaseIntelligence/base

Length of output: 21444


Keep durable nonce calls on an active executor loop.

The durable path blocks the calling master loop in _issue_blocking for up to 60s per nonce, and DurableAttestationNonceService.issue uses the shared async_sessionmaker/session_scope created from the main-loop engine. Running that coroutine in _run_coro_in_worker with a fresh asyncio.run() thread can fail only if the engine/session factory has loop-bound resources, and the pool executor is recreated per call. Keep this asyncio.get_running_loop() check, but avoid launching the worker loop directly from this tight poll path.

🤖 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 `@src/base/master/constation/orchestrator.py` around lines 313 - 336, Update
_issue_blocking so durable or awaitable nonce issuance runs on the already
active executor/event loop instead of invoking _run_coro_in_worker with a newly
created loop per poll. Preserve the existing asyncio.get_running_loop() check
and synchronous issuance behavior, and reuse the established executor-loop
scheduling mechanism so the shared session factory remains on its owning loop.

Comment on lines +66 to +164
hotkey = _require_nonblank("miner_hotkey", miner_hotkey)
key = _require_nonblank("api_key", api_key)
pod_id = _require_nonblank("instance_id", instance_id)

client = self.custody.client_factory(key)
try:
await self.custody.probe_fn(client)
except LiumAuthError:
logger.warning("lium key probe rejected (401) for miner_hotkey=%s", hotkey)
return ConstationVerdict(
ok=False,
reason=ConstationFailCode.LIUM_AUTH_REVOKED,
detail="probe_401",
)
except LiumError as exc:
logger.warning(
"lium key probe failed for miner_hotkey=%s status=%s",
hotkey,
getattr(exc, "status_code", None),
)
return ConstationVerdict(
ok=False,
reason=ConstationFailCode.PROBE_FAILED,
detail=type(exc).__name__,
)

try:
pod = await client.get_pod_raw(pod_id)
except LiumAuthError:
logger.warning(
"lium get_pod rejected (401) for miner_hotkey=%s instance_id=%s",
hotkey,
pod_id,
)
return ConstationVerdict(
ok=False,
reason=ConstationFailCode.LIUM_AUTH_REVOKED,
detail="get_pod_401",
)
except LiumNotFoundError:
logger.warning(
"lium get_pod not found for miner_hotkey=%s instance_id=%s",
hotkey,
pod_id,
)
return ConstationVerdict(
ok=False,
reason=ConstationFailCode.POD_HOTKEY_MISMATCH,
detail="pod_not_found",
)
except LiumRateLimitError:
logger.warning(
"lium get_pod rate limited for miner_hotkey=%s instance_id=%s",
hotkey,
pod_id,
)
return ConstationVerdict(
ok=False,
reason=ConstationFailCode.LIUM_RATE_LIMITED,
detail="get_pod_429",
)
except LiumError as exc:
logger.warning(
"lium get_pod failed for miner_hotkey=%s instance_id=%s status=%s",
hotkey,
pod_id,
getattr(exc, "status_code", None),
)
return ConstationVerdict(
ok=False,
reason=ConstationFailCode.PROBE_FAILED,
detail=type(exc).__name__,
)

bound = assert_pod_bound(pod_raw=pod.raw, expected_hotkey=hotkey)
if not bound.ok:
logger.warning(
"pod bind failed for miner_hotkey=%s instance_id=%s reason=%s",
hotkey,
pod_id,
bound.reason,
)
return bound

self.custody.store_probed_key(miner_hotkey=hotkey, api_key=key)
self._instance_by_hotkey[hotkey] = pod_id
logger.info(
"miner pod bound for miner_hotkey=%s instance_id=%s",
hotkey,
pod_id,
)
return ConstationVerdict(ok=True, reason=ConstationFailCode.OK)


def _require_nonblank(field_name: str, value: str) -> str:
normalized = value.strip()
if not normalized:
raise ValueError(f"{field_name} must be a non-empty string, got {value!r}")
return normalized

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Duplicated fail-closed probe logic and helper across custody.py and pod_binding.py.

register() (Lines 70-90) reimplements the same probe → classify-error logic already in LiumKeyCustody.register (constation_custody.py Lines 88-116), and _require_nonblank (Lines 160-164) is a verbatim copy of the identical helper in constation_custody.py. Since this is a fail-closed security path, future changes to error classification risk silently diverging between the two copies.

♻️ Suggested extraction
 # constation_custody.py
 class LiumKeyCustody:
+    async def probe_only(self, api_key: str) -> tuple[LiumClient, ConstationVerdict | None]:
+        """Probe api_key; return (client, None) on success or (client, fail_verdict)."""
+        key = _require_nonblank("api_key", api_key)
+        client = self.client_factory(key)
+        try:
+            await self.probe_fn(client)
+        except LiumAuthError:
+            return client, ConstationVerdict(ok=False, reason=ConstationFailCode.LIUM_AUTH_REVOKED, detail="probe_401")
+        except LiumError as exc:
+            return client, ConstationVerdict(ok=False, reason=ConstationFailCode.PROBE_FAILED, detail=type(exc).__name__)
+        return client, None
 # pod_binding.py
-        client = self.custody.client_factory(key)
-        try:
-            await self.custody.probe_fn(client)
-        except LiumAuthError:
-            ...
-        except LiumError as exc:
-            ...
+        client, fail = await self.custody.probe_only(key)
+        if fail is not None:
+            return fail
🤖 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 `@src/base/master/constation/pod_binding.py` around lines 66 - 164, Centralize
the probe error-classification flow and nonblank validation used by
pod_binding.register with the existing LiumKeyCustody.register implementation
and its _require_nonblank helper. Update register to call the shared custody
logic, remove the duplicated local probe handling and helper, and preserve the
current fail-closed verdicts and pod-binding behavior.

Comment on lines 401 to +414
async def _forward(self, primary: WorkAssignment, winner: WorkerAssignment) -> bool:
if self._constation_hook is not None:
try:
await self._constation_hook(
work_unit_id=primary.work_unit_id,
miner_hotkey=str(winner.miner_hotkey or ""),
metadata=dict(primary.payload or {}),
)
except Exception:
logger.exception(
"constation pre-forward hook failed for unit %s "
"(forward continues)",
primary.work_unit_id,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm orchestrator.run's real-world duration bound and whether _forward/hook is ever
# invoked outside the reconciliation DB transaction elsewhere.
rg -n -A15 'async def run' src/base/master/constation/orchestrator.py
rg -n 'session_scope' src/base/master/worker_reconciliation.py

Repository: BaseIntelligence/base

Length of output: 1051


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== orchestrator run implementation =="
sed -n '1,220p' src/base/master/constation/orchestrator.py

echo
echo "== worker reconciliation relevant sections =="
sed -n '150,230p' src/base/master/worker_reconciliation.py
sed -n '230,430p' src/base/master/worker_reconciliation.py

echo
echo "== constation hook wiring =="
fd -a 'custody_keys.py|constation.*' src | sed 's#^\./##' | rg 'custody_keys|constation|worker_reconciliation|orchestrator' || true
rg -n -A30 -B10 'make_constation_pre_forward_hook|constation_hook|ConstationPreForwardHook|build_constation_runtime|_constation_hook' src

Repository: BaseIntelligence/base

Length of output: 50377


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== custody_keys pre-forward hook =="
sed -n '127,240p' src/base/master/constation/custody_keys.py

echo
echo "== settings / constation bounds =="
rg -n -A8 -B6 'class .*Constation|duration_seconds|poll_timeout_seconds|gap_budget_seconds|min_interval_seconds|max_interval_seconds|max_polls|sidecar_timeout_seconds' src -g '*.py'

echo
echo "== runner duration handling =="
sed -n '1,260p' src/base/compute/constation_runner.py

echo
echo "== orchestrator rest =="
sed -n '220,380p' src/base/master/constation/orchestrator.py

Repository: BaseIntelligence/base

Length of output: 50377


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== bundle store put tail =="
sed -n '330,400p' src/base/master/constation/orchestrator.py

echo
echo "== session_scope implementation =="
rg -n -A40 'def session_scope|async def session_scope|class .*Session.*scope|contextmanager' src/base/db src/base/master/worker_reconciliation.py src/cli_app/main.py

echo
echo "== test coverage for hook timing =="
rg -n -A25 'test_reconciliation_constation_hook_called_before_forward|constation_hook_called|WorkerReconciliationService|reconcile_once|_forward' src -g '*test*.py' -g '*.py'

Repository: BaseIntelligence/base

Length of output: 3956


Decouple the constation attestation hook from the reconciliation DB transaction.

_forward runs inside reconcile_once’s session_scope, while the production hook invokes orchestrator.run(...), which drives a ConstationRunner with real timing and sidecar polling (default 5 min run budget, configurable max_polls, and sidecar timeout). A slow attestation run for one accepted unit can hold the DB transaction open and serialize the rest of the reconciliation pass until the run or its retries fail. Run the hook after the transaction commits, dispatch it as a background task, or wrap it with an explicit 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 `@src/base/master/worker_reconciliation.py` around lines 401 - 414, Decouple
the _constation_hook invocation in _forward from reconcile_once’s session_scope
so attestation work cannot hold the reconciliation DB transaction open. Schedule
the hook only after the transaction commits, preferably as a background task,
while preserving the existing payload, winner hotkey, exception logging, and
forward-success behavior; if post-commit dispatch is not available, enforce an
explicit bounded timeout.

@echobt
echobt merged commit 7694f18 into BaseIntelligence:main Jul 27, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants