{"assessments":[],"deployments":[],"fuzz":[],"identity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"interpretation":"Records acceptance and evidence. Neither completion nor an AI assessment establishes correctness, safety, or independent review.","jobId":"6fc92ac1-f4d3-4ce5-bea2-41b8b50e4c45","kind":"audit","nodes":[{"acceptedSubmissionHash":"aee4251f5378472cd8e5275525ae15784e22c078cac200f32f9c585dc4ae20bf","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","subagents":3,"tools":[]},"key":"audit_economics","kind":"code","role":"review","skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"be4f26e109f839581948a89a72d1c7c1f505f1aa19b2386c07ce14175f1d409d","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","subagents":3,"tools":[]},"key":"audit_flow","kind":"code","role":"review","skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":null,"dependsOn":["audit_math","audit_permissions","audit_economics","audit_flow"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"b89279670f5a00f5d26286edee00c97dd158b997031350a01cafe6e0329ad227","skillId":"audit-judge","subagents":4,"tools":[]},"key":"audit_judge","kind":"code","role":"review","skillHash":"b89279670f5a00f5d26286edee00c97dd158b997031350a01cafe6e0329ad227","skillId":"audit-judge","state":"waiting"},{"acceptedSubmissionHash":null,"dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","subagents":3,"tools":[]},"key":"audit_math","kind":"code","role":"review","skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","state":"failed"},{"acceptedSubmissionHash":"44f65d5d8a9c2057067aa8ada5ea793b16e101a92c17f238693c6b1817660f1d","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","subagents":3,"tools":[]},"key":"audit_permissions","kind":"code","role":"review","skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","state":"accepted"}],"objective":"Review Submission25/ only (read Submission25/AUDIT_REQUEST.md first). World source 580190a, NOT deployed; no real Celestao payment and no real grant has ever been made. It fixes audit 37a926e3, adds a wallet signature per GOLD grant (personal_sign, not the EIP-712 the report suggested; section 2 says why), and adds pre-sale payment fixes. The wallet-lock test fails on purpose until this audit is handled.\n\n1. Signature: forge, reuse or stretch one across sites, recipients, amounts or request ids. Message ambiguity, reason encoding, the origin taken from the request, expiry, the replay path before the check, and whether the test seam reaches production. Is personal_sign without chainId acceptable here?\n2. One reading, one order: any interleaving of reload, repeat, lapse, retire, payment and delivery that charges twice or loses a paid order. The 5-minute wait, the 3 tries, the renamed request id. Can a wallet reach another wallet's run?\n3. Stuck orders: can an order with a saved report be refunded? Can a healthy order reach 3 strikes? Races between strike, abandon, the lease and a late complete. The operator tool running beside the server.\n4. Retention: can prune_failed remove a run that can still be delivered or has a report? A late delivery or re-purchase after clearing. Does the cleared state reveal anything? Can the cleaner stop quietly?\n5. Polar: any input that passes validate and still fails compute because of location or timezone, so a buyer pays and is refunded.\n6. Privacy text against code: any sentence in world-wallet.js the code does not make true.\n7. Refund truth: anything that makes World refund a delivered order, or keep the money for one not delivered.\n\nKnown items are in AUDIT_REQUEST.md sections 2 to 7. Report severity, reproduction and fix. Not in scope: chart engines, report wording, 3D/rendering, media, AIMarket, Genesis.","parentJobId":null,"planHash":"cbcba30f94d3dcf902b6c814e148ff6a0a68bbe8c51005c3f45c0b6458f518a7","previousHash":"0c012acd8491d036d564cafe3520fc82654a8e5a4859807c8b4ef8172829c746","projectId":"6fc92ac1-f4d3-4ce5-bea2-41b8b50e4c45","publication":{"commit":null,"deliveredAt":null,"repoUrl":null},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"52161","feedbackHash":"c59821d6c933be6aee2ff8d01e0f209d6255b8e800b5cca1a6b16fdadf8570b2","nodeKey":"audit_economics","submissionHash":"aee4251f5378472cd8e5275525ae15784e22c078cac200f32f9c585dc4ae20bf","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52159","feedbackHash":"f6c8112ff6df0557a674cebf00c97210812080cdbb089274cf629e005d2eb5f9","nodeKey":"audit_flow","submissionHash":"be4f26e109f839581948a89a72d1c7c1f505f1aa19b2386c07ce14175f1d409d","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51476","feedbackHash":"d2ad0040a3e19b901417109aed5bddce4f2733bea0062025643212b94f080427","nodeKey":"audit_permissions","submissionHash":"44f65d5d8a9c2057067aa8ada5ea793b16e101a92c17f238693c6b1817660f1d","tag1":"review:submission","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"c7545f70eb3c029fc9c73d9a4079bb7b1e0f7c7498874f02fd76d85f847d419c","state":"blocked","submissions":[{"artifacts":[],"attempt":2,"bundleHash":null,"device":"dedc96e38388cb45","findings":[],"hash":"09d780e60ff49d95c71349e6388e795278d732676def1b84f4c121b97b4975ba","nodeId":"21c023b0-4cf5-493b-b95b-5e175af5e978","outcome":"failed","summary":"Failed to authenticate: this login reached its time limit and cannot be renewed. Run `claude auth login` to sign in again, or use `claude setup-token` and set CLAUDE_CODE_OAUTH_TOKEN for unattended jobs","treeHash":null,"usage":{"cachedInputTokens":0,"cost":{"source":"runtime","usdMicros":0},"inputTokens":0,"model":null,"outputTokens":0,"runtime":"claude","turns":1,"wallClockMs":1986}},{"artifacts":[],"attempt":3,"bundleHash":null,"device":"6b16b4979d227241","findings":[],"hash":"12b45cc336af7fb163375513b82c4102f11b7fab4fb6c0a8f845b4bbd95cbea7","nodeId":"6fd33636-d0b0-499c-9a26-8f0b04dce9f5","outcome":"failed","summary":"Failed to authenticate: this login reached its time limit and cannot be renewed. Run `claude auth login` to sign in again, or use `claude setup-token` and set CLAUDE_CODE_OAUTH_TOKEN for unattended jobs","treeHash":null,"usage":{"cachedInputTokens":0,"cost":{"source":"runtime","usdMicros":0},"inputTokens":0,"model":null,"outputTokens":0,"runtime":"claude","turns":1,"wallClockMs":1913}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"c97fd6a73e3737dc","findings":[],"hash":"2ad1ffbded74796330f59f0cc6773d905f2fbb73e34e885d1071bd1f9cf8089b","nodeId":"6fd33636-d0b0-499c-9a26-8f0b04dce9f5","outcome":"failed","summary":"Failed to authenticate: this login reached its time limit and cannot be renewed. Run `claude auth login` to sign in again, or use `claude setup-token` and set CLAUDE_CODE_OAUTH_TOKEN for unattended jobs","treeHash":null,"usage":{"cachedInputTokens":0,"cost":{"source":"runtime","usdMicros":0},"inputTokens":0,"model":null,"outputTokens":0,"runtime":"claude","turns":1,"wallClockMs":1868}},{"artifacts":[],"attempt":2,"bundleHash":null,"device":"e9049e5b12ba53ba","findings":[{"citation":"resolved","description":"calculate() sorts exceptions from processor.compute()/vault.complete() into three groups: refund now (NativeNondelivery, DocumentTooLarge), strike (NativeUnusable, any other Exception), and wait for ever with no strike (NativeUnavailable, sqlite3.Error, OSError, MemoryError). OSError is meant to stand for 'the disk is full', but in Python 3.11+ (the production image is 3.12) asyncio.TimeoutError is the builtin TimeoutError, which is a subclass of OSError. FileNotFoundError, PermissionError, ConnectionError and BrokenPipeError are subclasses too. So when an engine call fails the same way every time for one input, such as an engine-internal timeout (wait_for/asyncio.timeout inside the endpoint) or a missing ephemeris or data file for one date range, that paid order never gets a strike. failed_attempts stays 0 and vault.strike() is never called, so the 3-attempts/1-hour rule in AUDIT_REQUEST section 4 never fires. World keeps getting 'pending' and refunds nothing. The buyer has paid GOLD and gets no report and no refund until an operator notices the order in `orders list` and runs `orders refund`. Section 4 lists the uncounted classes as 'engine away or busy, database error, disk error, out of memory, a cancelled computation'. A timeout raised by the engine is none of these, and it is also not the >15-minute hang that the COMPUTE_LIMIT_MS cancel handles, because it raises well within the limit. This breaks request item 7 (World keeps the money for an order that was not delivered) and item 3. Fix: list the transient classes narrowly (sqlite3.OperationalError, OSError with errno ENOSPC/EIO/ENOMEM, MemoryError, NativeUnavailable). Catch TimeoutError/asyncio.TimeoutError and the other OSError subclasses (FileNotFoundError, PermissionError, ConnectionError) before that branch and send them to strike(), so they reach the existing 3-attempts/1-hour refund. Add a test where compute raises asyncio.TimeoutError and the run ends failed after the span.","line":103,"path":"Submission25/source/integrations/celestao/celestao_world/paid.py","reproduction":"Python check (3.14 here, same since 3.11): `asyncio.TimeoutError is TimeoutError` -> True; `issubclass(TimeoutError, OSError)` -> True; `try: raise asyncio.TimeoutError()\\nexcept (ValueError,OSError) as e: ...` takes the OSError branch. Path: in test_paid.py's Processor, make compute() run `raise asyncio.TimeoutError()` (or FileNotFoundError('ephe/seas_24.se1')) for every call. Prepare a run, bind an order, and send World deliveries 120 s apart (one per expired lease) for 2+ hours, i.e. far more than 3 attempts and over FAILED_ATTEMPTS_SPAN_MS. Expected: after 3 failed attempts spanning >=1 h the run becomes failed, and World gets terminal-failure CHART_NOT_GENERATED and refunds. Actual: every call answers kind='pending', runs.failed_attempts stays 0, state stays 'working', and the order is never refunded. The existing 'disk' test mode (raise OSError('no space')) shows the same uncounted path.","severity":"medium","snippet":"        except (NativeUnavailable,sqlite3.Error,OSError,MemoryError) as error:logging.getLogger('celestao.delivery').warning('delivery_pending order=%s reason=%s',b['orderId'],type(error).__name__)","title":"Any OSError, including TimeoutError, FileNotFoundError and ConnectionError from the engine, counts as 'engine away': a paid order that fails the same way every time is never struck, refunded or delive"},{"citation":"resolved","description":"compute() treats every returned Response that is not 200 and not 429/502/503 as a permanent nondelivery. paid.calculate() maps NativeNondelivery straight to vault.fail(...,'CHART_NOT_GENERATED'), and the same delivery call answers terminal-failure, so World refunds at once. AUDIT_REQUEST section 4 says a code fault must count as a strike and refund only after >=3 attempts and >=1 hour 'to catch a bad deployment'. But a bad deployment or a transient engine fault that the endpoint turns into a JSONResponse(status_code=500), or a 504 or 408 from an engine timeout, skips that guard. Each open paid order that is delivered during the fault is refunded on its first attempt, even though a later attempt would have made the report. The buyer is refunded and loses a reading that could have been made; the operator loses the sale and has no hour to react. The 1-hour window only protects faults that come back as exceptions. Fix: treat 5xx and 408 responses from the engine as a strike (raise NativeUnusable or a dedicated counted error) rather than NativeNondelivery. Keep NativeNondelivery for deterministic 4xx refusals such as 400 and 422, and for the profile/annual content checks.","line":77,"path":"Submission25/source/integrations/celestao/celestao_world/native.py","reproduction":"Stub the canonical endpoint so that compute() gets `JSONResponse({'detail':'engine error'}, status_code=500)` (or 504) once, then 200 with a valid result. Paid order: one World delivery call. Expected (as for a crash or RuntimeError): delivery_pending, failed_attempts=1, and the next attempt after the lease delivers the report. Actual: native.py:77 raises NativeNondelivery, paid.py:99 runs vault.fail, runs.state='failed', and the response is kind='terminal-failure' code='CHART_NOT_GENERATED'. World refunds, and the good 200 that would come next is never asked for.","severity":"low","snippet":"            if response.status_code!=200:raise NativeNondelivery('CHART_NOT_GENERATED')","title":"Any engine HTTP status other than 200/429/502/503 (500, 504, 408) refunds the paid order on the first attempt, skipping the 3-attempt / 1-hour guard against a bad deployment"}],"hash":"44f65d5d8a9c2057067aa8ada5ea793b16e101a92c17f238693c6b1817660f1d","nodeId":"a2a8e67c-09c3-4493-8ad6-373508f1a3d5","outcome":"completed","summary":"I found two defects in Submission25, both in how Celestao sorts engine failures into \"wait\", \"strike\" or \"refund now\". I found nothing to report in the grant signature path. Both findings are in `.imd-findings.json`. This was a single-reviewer pass of the Access Control, Trust Gap and Asymmetry guides, with no helpers.\n\n## Findings\n\n**1. Medium: a paid order can wait for ever, never delivered and never refunded** (`celestao_world/paid.py:103`)\n- **Cause:** the \"engine or disk is away\" branch catches all of `OSError`. On Python 3.11 and later (production runs 3.12), `asyncio.TimeoutError` is the built-in `TimeoutError`, which is a kind of `OSError`. So are `FileNotFoundError` and `ConnectionError`.\n- **Failing state:** an engine call that raises the same timeout, or the same missing data file, for one input on every attempt. That order never gets a strike, `failed_attempts` stays 0, and the 3-attempts/1-hour rule never fires. World keeps getting \"pending\" and keeps the GOLD until an operator runs `orders refund`.\n- **Checked:** I ran Python to confirm the exception classes (`issubclass(TimeoutError, OSError)` is True). I did not run it through the full server, because the server's dependencies (FastAPI) were not available on this machine.\n- **Fix:** keep only the real transient errors in that branch (database busy, disk full, out of memory, `NativeUnavailable`). Send timeouts and the other `OSError` kinds to `strike()`.\n\n**2. Low: one engine error response refunds at once, skipping the 1-hour guard** (`celestao_world/native.py:77`)\n- **Cause:** any response other than 200, 429, 502 or 503 raises `NativeNondelivery`. Delivery then fails the run and answers terminal-failure in the same call.\n- **Failing state:** an engine that returns 500 or 504 once and would succeed on the next try. The order is refunded on its first attempt, and the hour meant to catch a bad deployment only protects faults that come back as exceptions.\n- **Fix:** count 5xx and 408 responses as strikes. Keep the immediate refund for fixed refusals such as 400 and 422, and for the profile and annual content checks.\n\nNeither finding has a Foundry proof: the code is TypeScript and Python, so the Solidity test requirement does not apply.\n\n## Areas with nothing to report\n- **Signature:**\n  - The message binds origin, administrator, recipient, amount, reason, request id and expiry. The reason is JSON-escaped, and request ids are limited to `[A-Za-z0-9_-]`.\n  - The server only accepts `https://imdember.com` or a local origin, so a signature cannot move between sites.\n  - The test seam is not passed in production (`worker/app.ts:216`).\n  - The replay path only returns the stored result of the same grant.\n  - Leaving out the chainId is acceptable: the grant is a database write, not a chain transaction, and the origin plus request id bind it.\n- **One reading, one order:** reload, repeat, lapse and retire either return the same run or open a new one only after the old quote can no longer be paid. Every vault and World lookup is filtered by wallet, so one wallet cannot reach another's run.\n- **Stuck orders:** `abandon` refuses a run with a saved report. A late `complete` after `abandon` gets \"lease lost\" and saves nothing.\n- **Retention:** `prune_failed` only removes failed runs, and failed runs never have a report. A delivery after clearing still gets terminal-failure. The cleaner loop logs its errors and keeps running.\n- **Polar:** the latitude and timezone checks in `validate` match what `compute` needs for western and profile.\n\n## Leads I could not confirm\n- **Deleted rows left in the SQLite file.** SQLite may keep a deleted run's encrypted birth details in the database file, which would contradict the privacy text. The SQLite build here has `secure_delete` on by default, so I could not reproduce it. Check `PRAGMA secure_delete` in the production image.\n- **Engine behaviour.** The engine source is not in the package, so I could not see whether its endpoints raise `Time","treeHash":null,"usage":{"cachedInputTokens":2389235,"cost":{"source":"runtime","usdMicros":2010112},"inputTokens":59,"model":"claude-opus-5-5","outputTokens":31356,"runtime":"claude","turns":31,"wallClockMs":440191}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"8db4eebdd7bd2744","findings":[],"hash":"8ce4c5ec4f92568a77db5b1b8ecbeb6dc94e67a01d38857c5424048a271acd12","nodeId":"d0646403-d554-43d6-a386-10bccb806ff5","outcome":"failed","summary":"Failed to authenticate: this login reached its time limit and cannot be renewed. Run `claude auth login` to sign in again, or use `claude setup-token` and set CLAUDE_CODE_OAUTH_TOKEN for unattended jobs","treeHash":null,"usage":{"cachedInputTokens":0,"cost":{"source":"runtime","usdMicros":0},"inputTokens":0,"model":null,"outputTokens":0,"runtime":"claude","turns":1,"wallClockMs":2013}},{"artifacts":[],"attempt":3,"bundleHash":null,"device":"ca075d17c94a854b","findings":[{"citation":"resolved","description":"compute() only recognises an engine that is busy or away when the endpoint RETURNS a Response with status 429/502/503. The idiomatic FastAPI way to answer those statuses is to RAISE starlette.exceptions.HTTPException (the comment on the previous line says the baseline capacity lock and rate limit stay in force, and the same limiter answers 429 elsewhere). An HTTPException is a plain Exception, so in paid.py calculate() it falls through to the final `except Exception` and calls strike(). Three such answers spread over one hour (the engine busy at three delivery attempts, e.g. during a backlog) move the run to state failed with CHART_NOT_GENERATED, the next delivery answers terminal-failure, and World refunds an order that would have been delivered. Section 4 of the request states that 'engine away or busy' is not counted; this path counts it. The baseline endpoints are not in the package, so whether they raise rather than return could not be checked here; the mapping itself is the defect because it decides by class and HTTPException is not mapped.","line":75,"path":"Submission25/source/integrations/celestao/celestao_world/native.py","reproduction":"State: a paid order bound to a run (PaidTests.run_fixture). Make processor.compute raise fastapi.HTTPException(429,'RATE_LIMITED') (what a capacity lock raises). Call the delivery endpoint three times with self.time advanced by 1900000 ms between calls (attempts_on(run,order,3)). Expected (per AUDIT_REQUEST section 4 and the comment at paid.py line 102): every answer is 'pending' and failed_attempts stays 0, as it does for NativeUnavailable. Actual: answers are ['pending','pending','terminal-failure'], runs.state='failed', and World refunds the order on that answer. Fix: in compute() wrap the endpoint call with `except HTTPException as exc:` and raise NativeUnavailable for exc.status_code in (429,502,503), NativeNondelivery for other 4xx/5xx; or in calculate() add HTTPException with 429/502/503 to the pending branch.","severity":"low","snippet":"        if isinstance(response,Response):\n            if response.status_code in (429,502,503):raise NativeUnavailable('ENGINE_TEMPORARILY_UNAVAILABLE')\n            if response.status_code!=200:raise NativeNondelivery('CHART_NOT_GENERATED')","title":"A 429/503 raised as HTTPException by the engine endpoint counts as a failed attempt, so a busy engine can refund a healthy paid order"},{"citation":"resolved","description":"AUDIT_REQUEST section 3 says that during the five minutes between an unpaid order's expiry and World answering `lapsed` 'the checkout page asks the buyer to wait'. The code does not. When /api/celestao-checkout/state returns a pending order whose expiresMs has passed, the page renders the pay button disabled and shows no status text. The ORDER_EXPIRED message ('This unpaid quote expired. Wait 5 minutes, then return...') is only rendered from the error state, and the error state is only set by operate(), which cannot run because the button is disabled, or by quote(), which is never called while data.order exists. A buyer who reloads Celestao in that window is sent back to this same run (vault.prepare finds it by input digest and World answers lapsed=false), so they loop between two pages with no explanation until the window ends.","line":38,"path":"Submission25/source/src/world/CelestaoCheckout.tsx","reproduction":"State: checkout row with order_id set, economy_orders.status='pending', expires_ms = now-60000 (expired 1 minute ago, inside CELESTAO_LAPSE_GRACE_MS). Open /fortune-checkout/?run=<id> signed in as the buyer. Expected: a message that the quote expired and to wait 5 minutes (the ERRORS.ORDER_EXPIRED text). Actual: data.order is rendered with a disabled 'Sign payment of N GOLD' button and no message; pressing 'Check original order' changes nothing. Fix: when data.order.status==='pending' && data.order.expiresMs<=Date.now(), render the ERRORS.ORDER_EXPIRED text (role=alert) instead of the disabled button.","severity":"low","snippet":"<button className=\"celestao-gateway-primary\" disabled={busy||!controller||!data.ready||data.order.expiresMs<=Date.now()} onClick={()=>void operate(true)}>","title":"During the 5-minute lapse window the checkout page shows a silently disabled pay button; the 'wait 5 minutes' text is unreachable"},{"citation":"resolved","description":"The value World keeps in celestao_checkouts.input_hash is produced at vault.py line 100 by hmac.new(self._index_key, b'input|'+owner+'|'+canonical(payload), sha256). It is a keyed digest: nothing is encrypted and nothing can be decrypted, but anyone holding Celestao's storage key and World's database can confirm a guessed set of birth details (as section 6 of the request itself says). The Chinese text (經過加密的雜湊值) makes the same claim. 'Encrypted' promises more than the code does; the request asked for sentences the code does not make true, and this is one. The following clause ('cannot be directly turned back') is accurate.","line":93,"path":"Submission25/source/integrations/celestao/web/world-wallet.js","reproduction":"Input: any prepared run; read celestao_checkouts.input_hash on World and compare with hmac.new(index_key,b'input|'+owner+b'|'+canonical(payload),sha256).hexdigest() computed from the same birth details. Expected per the text: a ciphertext that requires a key to read. Actual: a deterministic keyed hash that equals the recomputed value, which anyone with the key can use to test guesses. Fix: say 'a keyed hash (digest) calculated from the birth details; it cannot be turned back into them, but someone holding both the key and World's records could confirm a guess' in both languages, or drop 'encrypted'.","severity":"info","snippet":"They include an encrypted digest calculated from the birth details, which cannot be directly turned back into them.","title":"Privacy text calls the World input digest 'encrypted'; the code computes a keyed hash (HMAC), not encryption"},{"citation":"resolved","description":"Vault.backup() (vault.py lines 249-258) only creates a backup file at an operator-chosen path and refuses to overwrite; nothing in the package schedules backups, records when one was taken, or deletes one. The 30-day bound therefore depends entirely on the operator deleting files by hand, which section 6 of the request acknowledges. A backup taken the day before a run was pruned and kept for 31 days makes this sentence false. Reported so the owner decides whether the sentence should become 'until the operator deletes the backup' or a deletion job is added; no code change is required for the vault itself.","line":93,"path":"Submission25/source/integrations/celestao/web/world-wallet.js","reproduction":"State: run R failed, failed_ms = T. Operator calls vault.backup(path) at T+29d; prune_failed(T+30d) removes R from runs. Expected per the text: path no longer contains R's input_blob after T+60d. Actual: the file is unchanged for ever unless deleted by hand; no code references it after creation. Fix: either reword, or add a retention job that removes backups older than 30 days from the configured backup directory and a test for it.","severity":"info","snippet":"Cleared data may remain in backup files for up to 30 more days.","title":"'Cleared data may remain in backup files for up to 30 more days' is not enforced by any code"}],"hash":"aee4251f5378472cd8e5275525ae15784e22c078cac200f32f9c585dc4ae20bf","nodeId":"21c023b0-4cf5-493b-b95b-5e175af5e978","outcome":"completed","summary":"The findings file is written. Bash never initialised in this session (sandbox bridge failure on every call), so nothing could be executed; all conclusions come from reading the code and the existing tests.\n\n**Outcome:** the Submission25 economics hold up under the interleavings I traced. Four items went into `.imd-findings.json`, none above Low.\n\n- **Low, native.py:75.** An engine endpoint that raises `HTTPException(429/503)` instead of returning a Response is not mapped to NativeUnavailable. It falls to the generic `except Exception` and counts as a strike, so three busy answers over an hour refund a healthy paid order. The baseline endpoints are not in the package, so whether they raise rather than return is unverified; the class-based mapping is the defect.\n- **Low, CelestaoCheckout.tsx:38.** During the 5-minute lapse window the page shows a silently disabled pay button. The ORDER_EXPIRED \"wait 5 minutes\" text is only reachable through an error path that cannot fire while an order row exists.\n- **Info, world-wallet.js:93.** \"Encrypted digest\" describes a keyed HMAC, not encryption.\n- **Info, world-wallet.js:93.** The 30-day backup bound is an operator promise with no code behind it.\n\n**Answers to the seven questions**\n\n1. **Signature.** No forge, reuse or stretch found. Every field in the message is either server-fixed or regex-bounded, the reason is JSON-escaped, and the origin is pinned to `https://imdember.com` by the handler before it is signed over. The replay path only returns the stored id and creates nothing. The seam is not wired by the worker and a test asserts that. personal_sign without chainId is acceptable here: GOLD is an off-chain ledger scoped to one origin, and a local-origin signature cannot reach production.\n2. **One reading, one order.** Reload, lapse, retire and the renamed request id compose correctly. The only double charge is the acknowledged grace-window race where a retired run is paid after all. Another wallet cannot reach a run: the vault keys by owner digest and World returns 409 on a wallet mismatch.\n3. **Stuck orders.** A saved report cannot be refunded: `abandon` refuses `complete`, and `complete` requires the exact working attempt, so a late result after abandon cannot save. Operator tool and server serialise through BEGIN IMMEDIATE.\n4. **Retention.** `prune_failed` only touches failed runs, which have no record and can only ever answer terminal failure. The cleaner logs errors and does not exit quietly. `cleared` is owner-bound.\n5. **Polar.** No validate-passes-compute-fails input found in the adapter itself; the engines are outside the package.\n6. **Privacy text.** Two wording items above. Everything else matches the code.\n7. **Refund truth.** No path makes World refund a delivered order, and no path keeps money for a run the vault has failed or pruned.\n\n**Not done:** no test could be run, so finding 1 has no executed reproduction, only the traced path. Chart engines, World ledger payment code and the recovery module were not read in depth.","treeHash":null,"usage":{"cachedInputTokens":1037729,"cost":{"source":"runtime","usdMicros":5609162},"inputTokens":354,"model":"claude-fable-5-1","outputTokens":44071,"runtime":"claude","turns":35,"wallClockMs":683306}},{"artifacts":[],"attempt":2,"bundleHash":null,"device":"6b37e4ab65246705","findings":[{"citation":"resolved","description":"compute() maps only 429/502/503 to NativeUnavailable (order waits). Every other non-200 Response, including a 500 from an engine crash, a 504 from a slow engine, a 507 from a full disk or a 408, raises NativeNondelivery. In paid.py calculate() (lines 96-100) NativeNondelivery goes straight to vault.fail(...,'CHART_NOT_GENERATED'): the run is marked failed on the first attempt, the same deliver() call answers terminal-failure (paid.py:145-149) and World refunds the order. This contradicts the stated policy in AUDIT_REQUEST section 4 (unexpected failures are a strike, at least 3 attempts over at least 1 hour; infrastructure failures wait) and the comment at paid.py:102-105. A single transient server-side error on the pinned endpoint therefore turns a deliverable, paid order into a refund, with no retry and no operator window. Whether the pinned endpoints emit a 500 Response object rather than raising was not verifiable from this package (the backend tree is not included); a raised exception takes the strike path, a returned 5xx Response takes the immediate-refund path. Fix: in compute(), treat status>=500 (and 408) as NativeUnavailable (wait), treat any other unexpected status as NativeUnusable (strike), and reserve NativeNondelivery for the explicitly documented 'cannot compute this input' outcomes (the profile used_sources check and the annual cover check already do this). Add a test in test_paid.py where the engine returns a Response with status 500 once and then 200, asserting the first deliver() answers 'pending' and the second 'delivered'.","line":77,"path":"Submission25/source/integrations/celestao/celestao_world/native.py","reproduction":"State: a run with a paid World order, state 'prepared'. Make the pinned chart endpoint return starlette Response(status_code=500) once (for example an engine subprocess crash mapped to 500), then 200 on the next call. Call POST /api/world/deliver once. Expected (section 4 policy): answer kind='pending', failed_attempts=1, no refund; the next delivery call after the lease computes and delivers. Actual: calculate() raises NativeNondelivery, vault.fail() sets state='failed', failure='CHART_NOT_GENERATED', the same call answers kind='terminal-failure' with provider-confirmed-nondelivery, and World refunds the GOLD. The second, healthy engine call never happens. The run can only be bought again as a new order.","severity":"medium","snippet":"            if response.status_code!=200:raise NativeNondelivery('CHART_NOT_GENERATED')","title":"A transient non-200 engine response (500/504/507/408, or any 4xx) refunds the paid order at once instead of striking or waiting"},{"citation":"resolved","description":"The sentence (zh: 僅限有效登入的相同錢包讀取) promises exclusivity that the code does not provide. vault.py:39-40 derives a single AESGCM cipher and index key from the one server storage key (Settings.storage_key); every run's input_blob and every record's result_blob and metadata_blob are sealed with that key, with the owner digest only as associated data (vault.py:89,119,203). Vault.read()/ _open() need no wallet-held secret, and backup() copies the ciphertext to a file the same key opens. What the code enforces is that the HTTP API returns a record only to the session whose wallet digest matches; anyone with the server key and the database file (the operator, a backup holder, a compromised host) can read all wallets' birth details and reports. The text elsewhere is careful about what remains after cleanup and about World's keyed digest, so this sentence stands out as the one claim stronger than the code. Fix: change the sentence to say the data is encrypted with a key held by the Celestial Atlas server and is returned only to the same signed-in wallet, so the operator (and anyone holding the server key and database) can read it; or, if exclusivity is wanted, derive per-wallet keys from wallet-signed material, which is a design change.","line":92,"path":"Submission25/source/integrations/celestao/web/world-wallet.js","reproduction":"State: any completed run for wallet W. Input: on the server, Vault(settings.database, settings.storage_key).read(W, record_id) or a direct _open(result_blob, owner+'|record|'+id) without any session or signature from W. Expected per the text: unreadable without W signed in. Actual: the plaintext report and its input (birth details) are returned; no wallet key material is involved anywhere in vault.py.","severity":"low","snippet":"After explicit storage consent, birth details and complete reports are encrypted on the Celestial Atlas server and can be read only by the same signed-in wallet.","title":"Privacy text says stored birth details and reports 'can be read only by the same signed-in wallet', but one server-held key decrypts every wallet's data"}],"hash":"be4f26e109f839581948a89a72d1c7c1f505f1aa19b2386c07ce14175f1d409d","nodeId":"d0646403-d554-43d6-a386-10bccb806ff5","outcome":"completed","summary":"The review is written to `.imd-findings.json` with two substantiated findings. The Bash sandbox could not initialize in this session, so nothing was executed; every conclusion comes from reading the Submission25 tree, and no test proofs could be run (none were required, since the code under review is Python and TypeScript, not Solidity).\n\n**Findings recorded**\n\n- **Medium, native.py line 77.** Any non-200 engine response other than 429/502/503 raises NativeNondelivery, which calculate() in paid.py turns into an immediate vault.fail and a terminal-failure answer. A single transient 500, 504, 507 or 408 Response therefore refunds a paid, deliverable order on the first attempt, bypassing the documented three-strike, one-hour policy. Whether the pinned endpoints return such a Response rather than raising was not verifiable from this package. Fix: map 5xx and 408 to NativeUnavailable, other unexpected statuses to NativeUnusable, and keep NativeNondelivery for the explicit cannot-compute outcomes.\n- **Low, world-wallet.js line 92.** The privacy text says stored birth details and reports \"can be read only by the same signed-in wallet\". The vault seals everything with one server-derived key and no wallet-held material, so the operator, a backup holder or a compromised host can read all wallets' data. The sentence should describe server-held encryption and API-level restriction instead.\n\n**Checked and found consistent with the design**\n\n- Signature: the message binds origin, administrator, recipient, amount, JSON-encoded reason, request id and expiry. The request id regex excludes newlines, so no field can absorb another. The page and server build the message from the same values. The replay path returns only an already-written grant for the same wallet and request id, and a failed batch writes no row. The worker never passes the recovery seam. personal_sign without chainId is acceptable here: GOLD is an off-chain ledger, the origin is pinned to the production host, and the wallet shows the text.\n- One reading, one order: expired orders stay status pending, so the lapsed check fires. Retired runs are renamed with a character the client cannot submit. Every vault read is owner-scoped and World's checkout rows are wallet-bound.\n- Stuck orders: strike, abandon, fail and complete all run under BEGIN IMMEDIATE on one file, so a late complete after abandon gets LEASE_LOST and a saved report refuses abandon. CancelledError is a BaseException and never strikes. The in-process active map prevents a second claim while a computation runs.\n- Retention: a failed run can never hold a record, so prune_failed cannot delete a deliverable run, and the tombstone keeps the refund path open. The cleaner logs and sleeps on any error rather than dying.\n\n**Not verified**\n\nThe economy ledger and the pinned chart engine are not in the package, so the five-minute lapse grace and the polar question beyond the latitude gate could not be checked against code.","treeHash":null,"usage":{"cachedInputTokens":2433145,"cost":{"source":"runtime","usdMicros":5251761},"inputTokens":1090,"model":"claude-fable-5-1","outputTokens":41356,"runtime":"claude","turns":35,"wallClockMs":618882}},{"artifacts":[],"attempt":2,"bundleHash":null,"device":"28e346843ec15530","findings":[],"hash":"d0226182e7691f895f780715b381ce79385b1bdfe04847d539082653e4f02fcc","nodeId":"6fd33636-d0b0-499c-9a26-8f0b04dce9f5","outcome":"failed","summary":"Failed to authenticate: this login reached its time limit and cannot be renewed. Run `claude auth login` to sign in again, or use `claude setup-token` and set CLAUDE_CODE_OAUTH_TOKEN for unattended jobs","treeHash":null,"usage":{"cachedInputTokens":0,"cost":{"source":"runtime","usdMicros":0},"inputTokens":0,"model":null,"outputTokens":0,"runtime":"claude","turns":1,"wallClockMs":1843}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"3baa2091028c32c1","findings":[],"hash":"dec344214ccc96d3289f6f3148d77cea0fd42a7d1df64680ec4054c7710715d9","nodeId":"21c023b0-4cf5-493b-b95b-5e175af5e978","outcome":"failed","summary":"Failed to authenticate: this login reached its time limit and cannot be renewed. Run `claude auth login` to sign in again, or use `claude setup-token` and set CLAUDE_CODE_OAUTH_TOKEN for unattended jobs","treeHash":null,"usage":{"cachedInputTokens":0,"cost":{"source":"runtime","usdMicros":0},"inputTokens":0,"model":null,"outputTokens":0,"runtime":"claude","turns":1,"wallClockMs":1929}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"ff35db055462d2ad","findings":[],"hash":"f853cf4f45a31ed6cbd6c20cb2114bf5cd075221837c5385f83d9cbab1e2c307","nodeId":"a2a8e67c-09c3-4493-8ad6-373508f1a3d5","outcome":"failed","summary":"Failed to authenticate: this login reached its time limit and cannot be renewed. Run `claude auth login` to sign in again, or use `claude setup-token` and set CLAUDE_CODE_OAUTH_TOKEN for unattended jobs","treeHash":null,"usage":{"cachedInputTokens":0,"cost":{"source":"runtime","usdMicros":0},"inputTokens":0,"model":null,"outputTokens":0,"runtime":"claude","turns":1,"wallClockMs":1944}}],"verification":[]}