# Audit report

> Review only the final delta from d4af978 to this pinned commit, described in docs/review-credit-fixes.patch and docs/review-credit-findings.json. Original paid review job5e2ee286-9298-4fa2-a0d0-5c4b387c7dc8 already examined the prior native prepaid route and finite caps; do not repeat its entire audit. Verify the corrections: agent requires surplus_credit for fresh dispatch; exact-ID explicit unsigned pre-reservation capacity deferrals queue the same ID; inactive uncertain delivery after the original800-second window fails the agent review without releasing monetary holds, approving, or retrying the paid call; final output/input quote cannot shrink; readiness honors configured ceiling; dated canonical-decimal capacity is bound to at most two configured project IDs, all other projects stay at8. Look for concrete introduced replay/accounting/authority defects. Read full changed mirrors plus now-included unchanged vendor quote/response/policy and completion-stream. Existing ledgers, wallets, contracts, model/effort, budgets and histories are unchanged. Deployment manifests explicitly distinguish historical verified source from unpublished candidate. No contract or customer-fund changes. Targeted tests and typecheck passed. Report material defects separately from documentation/style and clearly distinguish unchanged risks. This is the final corrective delta, not a request to expand scope or repeat unchanged suites.

| | |
|---|---|
| Repository | https://github.com/contractclaus/claus-network |
| Commit | `07def425130b9e2e2f721030cef305c080a74f52` |
| Job | `6fe2d959-fa84-46d9-9c7a-b3b9b63497a7` |
| Judged | 2026-10-13 15:17 UTC |
| Findings | 1 medium · 1 low · 5 info |

Four agents audited the code as it is at `07def42`, each in one area (math, permissions, economics, control flow),
and a judge reproduced, merged and ranked what they found, then read the code once more itself. Nothing in the repository was changed or deployed.

## Findings

### 1. Medium: Only credit_busy carries admission:'deferred'; every other exact-ID unsigned pre-reservation refusal turns the review uncertain, then terminally fails it as inference_not_reserved

`integration/payment-review/src/index.js:157`

```
      if(!admission.ready)return c.json({id,error:admission.reason,payment:'not_signed',...(admission.reason==='credit_busy'?{admission:'deferred'}:{})},503);
```

MATERIAL, introduced by this delta (liveness/attempt accounting; no customer funds move, no monetary hold is taken on this path). The 'Admission race' correction says exact-ID unsigned pre-reservation busy/capacity deferrals requeue the same agent row. The payer stamps every POST-time workAdmission refusal with the exact id and payment:'not_signed', but attaches admission:'deferred' only for credit_busy. The agent (integration/agent-review/network-review.ts:120-125) requeues only when admission==='deferred' and error is credit_busy or credit_capacity_wait; everything else falls to `if(!response.ok)throw` and the catch at line 132 sets state='uncertain'. credit_exhausted is the same capacity condition observed one check earlier: credit-work-admission.js:18 tests `remaining<2000000` before the busy test at line 19, so a concurrent Builder reservation that lands between the agent's admission GET and its POST while the lifetime budget is within 4 USDC of its ceiling produces credit_exhausted, not credit_busy. credit_unavailable (claus_credit_work_control.frozen flipped by a Builder overrun) is equally transient and unsigned. For all of these the review holds the single claus_network_review_active slot for 800 s, networkReviewStatus then calls GET /api/requests/<id>, which finds no row and answers 404 not_found via confirmAbsent, and lines 159-161 set state='failed' {error:'inference_not_reserved'}. Because the review id is nr_+hash(input) and submitNetworkReview returns the existing row (lines 61-62), the identical proposal evidence can never be re-reviewed, and one of the planned 'at most two further decisions' and one of the day's eight admissions is consumed by a request that never reached a quote. Merged from audit_economics 8f29ceca, audit_math fd776c64 (variant a), audit_flow c247d32d and audit_permissions ce215781. Minimal fix: in index.js:157 emit admission:'deferred' for every pre-reservation workAdmission refusal (they are all unsigned and pre-reservation by construction), or at least for the transient set {credit_busy, credit_exhausted, credit_unavailable}; alternatively have the agent fail immediately, rather than go uncertain, on any payer body with id===effectId, payment==='not_signed' and no admission marker. Post-reservation 502 payment_requires_reconciliation responses and transport errors must keep their current uncertain handling.

**Reproduction**

State: NETWORK_REVIEW_FRESH_RAIL=credit_work, SURPLUS_CREDIT_ENABLED=true, pool funded, claus_payment_budget ceiling=100000000 committed=97000000 (remaining 3000000), no active claus_credit_work row, agent row nr_X queued. 1) Agent GET /api/admission/network-review:nr_X?maximumMicroUsdc=2000000 -> workAdmission: remaining 3000000>=2000000, busy=false -> {ready:true,rail:'surplus_credit'}; agent claims the row (state='running', started_at=now). 2) Before the agent's POST, a Builder POST with Idempotency-Key build_<24hex>:model:1 reserves 2000000 (committed=99000000) and completes within the same second (row inactive, busy=false). 3) Agent POST /api/completion Idempotency-Key network-review:nr_X -> index.js:156 workAdmission -> credit-work-admission.js:18 remaining=1000000<2000000 -> waiting('credit_exhausted') -> line 157 responds 503 {id:'network-review:nr_X',error:'credit_exhausted',payment:'not_signed'} with no admission field. EXPECTED (docs/review-credit-routing.md line 9, docs/review-credit-findings.json 'Admission race'): the agent returns the row to state='queued' with available_at=now()+60s, exactly as it does for credit_busy. ACTUAL: network-review.ts:120 is false, line 125 throws, line 132 sets state='uncertain'; after 800 s networkReviewStatus receives 404 {error:'not_found'} and sets state='failed' {error:'inference_not_reserved'}; submitNetworkReview for the same input returns that failed row forever. Executed: the unmodified network-review.ts (sha256 93a9462b...) was run under Node 24.21 with a stubbed db and fetcher (admission GET -> ready/surplus_credit; POST -> the 503 bodies above). Results: credit_busy and credit_capacity_wait deferrals -> 'queued' (controls pass); credit_exhausted, credit_unavailable, credit_ceiling_mismatch, credit_not_configured -> 'uncertain', then after a status call at started_at+801 s with payer 404 not_found -> 'failed' {error:'inference_not_reserved'}.

### 2. Low: Overlapping reserveCredit statements: the loser's 23505 on claus_credit_work_one_active is uncaught and surfaces as a bare 502 without id, so the genuine admission race is not deferred

`integration/payment-review/src/credit-provider.js:65`

```
    const reserved=await store.reserveCredit(db,{id,hash,maximum,activeMs:timing.activeMs,binding:{address:pool.deposit_address,keyId:pool.key_id,transaction:pool.deposit_tx,
```

MATERIAL but rare, introduced gap in the 'Admission race' correction (liveness only; the losing statement rolls back entirely, so no hold or ID claim is left behind). allowCapacityDeferral only converts an EMPTY reserveCredit result (the admitted CTE matched nothing because the other reservation was already visible) into {id,error:'credit_capacity_wait',admission:'deferred',payment:'not_signed'}. When the agent's and a Builder's reserveCredit statements actually overlap, the second waits on the claus_payment_budget row lock, re-evaluates `committed BETWEEN ...` on the new row version but keeps its original snapshot for the `NOT EXISTS(SELECT 1 FROM claus_credit_work WHERE active)` subquery, passes admission and then violates the partial unique index claus_credit_work_one_active (credit-work-store.js:21; its own comment at lines 54-55 describes exactly this). The resulting 23505 is thrown from line 65, which is outside the try that starts at line 79, so creditCompletion rejects; completion-stream.js:13-16 logs completion_handler_failed and returns failure() = 502 {error:'payment_requires_reconciliation'} with no id and no deferral marker. The agent then goes uncertain and, after 800 s, fails terminally with inference_not_reserved as in the previous finding. Distinct mechanism and fix location from the index.js:157 finding (audit_math fd776c64 variant b). Minimal fix: wrap store.reserveCredit in try/catch and, when allowCapacityDeferral is set and error.code==='23505' with constraint 'claus_credit_work_one_active', return the same 503 credit_capacity_wait deferral; any other 23505 (for example claus_payment_ids_pkey) must keep the current non-deferral behaviour because that ID is already claimed or fenced.

**Reproduction**

State: as in the previous finding but with remaining>=4000000 and no active work row. Run a Builder POST (build_<24hex>:model:1) and the agent POST (network-review:nr_X) so that both pass workAdmission (busy=false) and their reserveCredit statements execute concurrently. EXPECTED (docs/review-credit-findings.json 'Admission race'): the loser answers with an exact-ID unsigned deferral and the agent requeues nr_X. ACTUAL: the loser's statement raises 23505 on claus_credit_work_one_active; credit-provider.js:65 propagates it; streamCompletion returns 502 {"error":"payment_requires_reconciliation"}; the agent marks nr_X 'uncertain' and after 800 s 'failed' {error:'inference_not_reserved'}. Executed: completion-stream.js run verbatim under Node 24.21 with a handler that rejects with {code:'23505',constraint:'claus_credit_work_one_active'} produced `status 502 body {"error":"payment_requires_reconciliation"}`; feeding that body to the unmodified network-review.ts runNetworkReview produced state 'uncertain', and a status call at started_at+801 s with payer 404 produced 'failed' {error:'inference_not_reserved'}.

### 3. Info: Documentation: the elevated recovery limit is a global-day ceiling compared against all projects' reviews, not a per-project allowance; 'all others retain eight' overstates it

`integration/agent-review/network-review.ts:66`

```
    WHERE (SELECT count(*) FROM claus_network_reviews WHERE created_at>=date_trunc('day',now() AT TIME ZONE 'UTC') AT TIME ZONE 'UTC')<${networkReviewDailyLimit(Date.now(),process.env,input.projectId)}
```

Documentation/style, not a replay, accounting or authority defect. networkReviewDailyLimit returns 8..16 only for an allow-listed projectId (verified: allowlisted -> 10, other project -> 8, no projectId -> 8, limit '010' -> 8, three IDs -> 8, wrong UTC day -> 8), but the operand it is compared against is count(*) of ALL reviews created today. The allow-listed project's extra attempts share one counter with everyone else, so an allow-listed project can consume the whole day and leave other projects with zero, and ordinary morning submissions reduce the allow-listed project's recovery headroom. This mirrors the network side (src/approvals/limits.mjs:30 compares requestedGlobalDay against the shared global-day counter), so the tiers are consistent and nothing resets, but docs/review-credit-routing.md line 5 and docs/operations.md line 128 say other projects 'retain eight', which reads as a guaranteed allowance. Merged from audit_economics 279b8b72 and audit_permissions d7ad8b71. Fix: reword the docs to say eight is the ceiling for non-allow-listed projects and capacity is shared, or scope the extra headroom per project (global_count<8 OR project_count_today<limit-8).

**Reproduction**

Env: NETWORK_REVIEW_RECOVERY_PROJECTS=prj_45b80d1b-453d-4ebc-a7bd-e15098e6c5fb, NETWORK_REVIEW_RECOVERY_LIMIT=16, NETWORK_REVIEW_RECOVERY_DAY=<today UTC>. The allow-listed project submits 16 distinct valid proposals (count 0..15 < 16, all inserted). prj_6a2a275a-abc7-4e29-b91e-4e004ebb58ef then submits its first review of the day: limit=8, count(*)=16, 16<8 false -> INSERT returns no row -> submitNetworkReview throws network_review_capacity. Expected per the docs' wording: admitted, since that project used none of its eight. Actual: refused for the rest of the UTC day. networkReviewDailyLimit values above were obtained by calling the exported function from the unmodified file under Node 24.21.

### 4. Info: Unchanged risk: terminal failure of an inactive uncertain delivery frees the agent slot while each 2 USDC work-store hold is never released, so unresolved exposure accumulates toward the lifetime ceil

`integration/payment-review/src/credit-work-store.js:45`

```
  RETURNING CASE WHEN accounted_cost=0 AND dispatched_at IS NULL THEN reserved_max ELSE 0 END AS released
```

Not a defect of this delta; this is the documented design (credit-work-store.js lines 1-4 and docs/review-credit-routing.md line 9 'the payer ledger keeps the full unresolved exposure'), recorded because the task asks to distinguish unchanged risks. The new branch at network-review.ts:153-157 correctly marks the review failed with paymentHoldRetained:true and never approves, re-POSTs or touches the payer. On the payer, expireCredit releases committed only when accounted_cost=0 AND dispatched_at IS NULL; a dispatched row that expires keeps accounted_cost NULL (released=0), finishCredit never touches a row already uncertain, and /api/reconcile/:id only echoes workResult for claus_credit_work rows. Before the delta an uncertain review kept the unique claus_network_review_active slot forever, which incidentally capped this path at one hold; now each terminated review lets the next one reserve a fresh 2000000. Exposure is bounded by the 100/500 USDC lifetime ceiling and real spend by the live balance check at credit-provider.js:96. Operators should expect credit_exhausted earlier than the nominal ceiling once several reviews end uncertain. Merged from audit_math b070d253 and audit_permissions 5132f808.

**Reproduction**

State: ceiling=100000000, committed=0. Repeat: review nr_i admitted, reserveCredit commits +2000000, startCredit marks submitting, the provider never answers; at active_until expireCredit sets status='uncertain', active=false, released=0 (accounted_cost stays NULL because status was not 'reserved'); after 800 s the agent marks nr_i failed {error:'inference_delivery_unknown',paymentHoldRetained:true} and the unique active index is free. After 50 such rows committed=100000000 and workAdmission returns credit_exhausted for every further review although no charge was ever confirmed. Expected per the documented design: exactly this, until an operator ledger action outside this code.

### 5. Info: Unchanged risk: the inactive-uncertain terminal path runs only when networkReviewStatus or cancelNetworkReview is called; no scheduler is in the mirror

`integration/agent-review/network-review.ts:143`

```
 if(!Number.isFinite(startedAt)||Date.now()-startedAt<=800000)return visible(row);
```

Unchanged risk, not introduced. The bound the delta adds (fail an inactive uncertain credit delivery after the 800 s window) is reachable only from the pull-driven status/cancel entry points. The agent-side caller cadence is not part of the supplied mirrors. If no status poll arrives after started_at+800 s, the uncertain row keeps the claus_network_review_active slot indefinitely and every new submitNetworkReview fails with network_review_capacity, the same condition the prior job's 'Indefinite uncertain execution' finding described. From audit_economics c56bf123. Fix if wanted: an operator-visible reconciliation sweep that calls networkReviewStatus for running/uncertain rows older than 800 s, or documentation that the status poll is the only release path.

**Reproduction**

State: agent row nr_X state='uncertain', started_at=T; payer row network-review:nr_X status='uncertain', active=false, active_until<now. Input: no call to networkReviewStatus or cancelNetworkReview after T+800 s. Actual: the row stays 'uncertain'; any other submitNetworkReview INSERT hits the unique partial index and throws network_review_capacity. Expected: a release path that does not depend on an external poll, or a documented operator procedure.

### 6. Info: Robustness: execution.activeUntil is the raw Postgres timestamptz text, and the terminal branch silently never fires if Date.parse cannot read it

`integration/payment-review/src/index.js:70`

```
  const workResult=row=>({...creditResult(row),id:row.id,rail:'surplus_credit',execution:{active:row.active,activeUntil:row.active_until},...(row.status==='failed'&&row.accounted_cost==='0'&&row.dispatched_at===null&&row.outcome?.payment==='not_signed'
```

Documentation/style. readCredit selects active_until::text, so the wire value is the session DateStyle rendering. Verified under Node 24.21: Date.parse accepts the default ISO rendering ('2026-10-13 14:16:05.263+00' -> 1791900965263) but returns NaN for DateStyle=German ('13.10.2026 14:54:24.477768 UTC'). In that case network-review.ts:154 never satisfies Number.isFinite and an inactive uncertain review stays uncertain on every status call, which is exactly the condition this delta set out to bound. Neon's default is ISO and only an operator could change it, so this is not reachable today. From audit_permissions 193a9507. Fix: emit a canonical ISO string (to_char(active_until AT TIME ZONE 'UTC','YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')) or drop the ::text cast, and have the agent treat an unparseable activeUntil explicitly.

**Reproduction**

Payer database session with DateStyle=German; work row network-review:nr_X status uncertain, active=false, active_until in the past. GET /api/requests/network-review:nr_X returns execution:{active:false,activeUntil:'13.10.2026 14:54:24.477768 UTC'}. Expected: agent marks the review failed {error:'inference_delivery_unknown',paymentHoldRetained:true}. Actual (executed against the unmodified network-review.ts with a stubbed payer response carrying that string): the row remains 'uncertain'. The same harness with the ISO rendering '2026-10-13 15:14:42.369+00' produced 'failed' with paymentHoldRetained:true, confirming the branch works for the default DateStyle.

### 7. Info: Verification limit: both mirrors import modules absent from the tree, so 'targeted tests and typecheck passed' cannot be rerun here and several guards were verified by reading only

`integration/payment-review/src/credit-provider.js:3`

```
import {requestBudget} from '../vendor/src/request-budget.js';
```

Not a code defect; recorded so the requester knows which claims rest on unmirrored code. The payer mirror imports vendor/src/request-budget.js, inference-transport.js, images.js, funding.js, outcomes.js, vendor/completion.js, src/retain-completion.js, legacy.js, budget.js (confirmAbsent, which the 404 fence depends on), recovery.js, credit-admission.js, builder-transport.js and response-stream.js; the agent mirror imports ./store.js and ./inference-transport.js; none are present and hono is not installed. No test under test/ exercises either mirror. Verified here: docs/review-credit-fixes.patch applies cleanly to d4af978 and reproduces the four changed code files byte for byte; docs/agent-review-source.json hashes match the agent files at its stated historical lineage (network-review.ts 068d2664... at e5df7c2) and not the working tree (93a9462b...), exactly as its new scope text says; the agent requires rail==='surplus_credit' before claiming; allowSmallerOutput:false makes quoteWithinBudget throw quote_refused, which lands in the not_signed/amount '0' branch; workAdmission refuses a configured ceiling below 2000000 and a non-numeric one; the project allow-list regex matches the prj_+UUID ids produced by src/identity/index.mjs:22 and rejects more than two entries or non-canonical limits. Not verified: requestBudget's acceptance of a configured ceiling between 2000000 and 3000000 together with header 2000000, retainCompletion on platforms without waitUntil, and the agent caller cadence. No Solidity is part of this delta, so no Foundry proof applies. Merged from audit_economics 93623be8 and audit_flow 6a3e7dbf.

**Reproduction**

From the repository root: `node -e "import('./integration/payment-review/src/index.js')"` fails with ERR_MODULE_NOT_FOUND for 'hono'; `node -e "import('./integration/payment-review/src/credit-provider.js')"` fails for ../vendor/src/request-budget.js; `node --experimental-strip-types -e "import('./integration/agent-review/network-review.ts')"` fails for ./store.js. Expected per the task statement: targeted tests and a typecheck a reviewer can rerun. Actual: only the network package's own suite is runnable; the agent mirror was exercised in this review only by supplying stub store/schema/transport modules outside the repository.

---

Judge's submission `a4ed642a4882e38e3eb4ffb14e6ca61fb0e61e72fa9be7febf64d64fd8367964`, accepted on the IdentityMD network. Acceptance means the report met the job's checks;
it is not a guarantee that the code has no other defects.
