Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,16 @@ See

- Public application: `https://commit-protocol.vercel.app`
- Deployed application source commit:
`d25e689b0d5c681755751da257700f0d3f7974d1`
`53fb52f2d8d7c5a3636810501b740d859d5a2c14`
- Deployed application source tree:
`5553aa58ab006c85000c5a2b106988da2b61f002`
`91c5f458dd77f7d38f0c8107f00eb15a74c3ce37`
- Vercel production deployment:
`dpl_Cwh63QydtcGyVD9MeZ7jrSo3A1QE`
`dpl_BvXSZgubPSzs3Z9cyck6eY5dzvDt`
- Served coordinator: `0xEE21cCFF8f3755487f774BFd5Da9Ff51D5688581`
- Production smoke checks: `/`, `/app`, `/verify`, health, typed index lookup,
typed transaction lookup, security headers, and browser verification action:
**passed**
- GitHub Actions `Verification` run `35140950751`: **passed**
- GitHub Actions `Verification` run `35142284628`: **passed**

The complete production release record is in
[`docs/PRODUCTION_RELEASE_2026-09-16.md`](./docs/PRODUCTION_RELEASE_2026-09-16.md).
Expand Down
25 changes: 16 additions & 9 deletions components/application/claim-mission-flow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import {
ShieldCheck,
WalletCards,
} from "lucide-react";
import {
useState,
} from "react";
import { useState } from "react";
import {
formatGenAmount,
trackCommitTransaction,
Expand Down Expand Up @@ -97,6 +95,13 @@ export function ClaimMissionFlow({
setDeliveryBusy,
] = useState(false);

const activeClaimRecord =
claimRecord !== null
&& claimRecord.missionId === missionId
&& claimRecord.beneficiary.toLowerCase() === wallet.address.toLowerCase()
? claimRecord
: null;

function resetReview() {
setQuote(null);
setProgress(null);
Expand Down Expand Up @@ -152,6 +157,8 @@ export function ClaimMissionFlow({
txId,
});
setClaimRecord({
missionId: quote.snapshot.mission.missionId,
beneficiary: quote.snapshot.beneficiary,
transactionId: txId,
amount: quote.snapshot.missionClaimable,
});
Expand Down Expand Up @@ -209,7 +216,7 @@ export function ClaimMissionFlow({

async function refreshDelivery() {
if (
claimRecord === null
activeClaimRecord === null
|| deliveryBusy
) {
return;
Expand All @@ -221,17 +228,17 @@ export function ClaimMissionFlow({
setDelivery(
await observeExternalDelivery(
wallet.client,
claimRecord.transactionId,
activeClaimRecord.transactionId,
{
recipient: wallet.address,
amount: claimRecord.amount,
amount: activeClaimRecord.amount,
},
),
);
} catch (caught: unknown) {
setDelivery(
unverifiedExternalDelivery(
claimRecord.transactionId,
activeClaimRecord.transactionId,
caught instanceof Error
? caught.message
: "The delivery observation could not be completed. No delivery outcome is claimed.",
Expand Down Expand Up @@ -515,7 +522,7 @@ export function ClaimMissionFlow({
</div>
) : null}

{claimRecord !== null ? (
{activeClaimRecord !== null ? (
<div className="claim-delivery">
<div className="claim-delivery-heading">
<div>
Expand Down Expand Up @@ -552,7 +559,7 @@ export function ClaimMissionFlow({
<dl>
<div>
<dt>Parent claim</dt>
<dd>{claimRecord.transactionId}</dd>
<dd>{activeClaimRecord.transactionId}</dd>
</div>
<div>
<dt>Triggered child</dt>
Expand Down
8 changes: 4 additions & 4 deletions docs/AGENT_TANK_SUBMISSION.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ uses the SDK's authoritative eligibility, charge, and appeal operations.
- Public app: `https://commit-protocol.vercel.app`
- GitHub: `https://github.com/Manablaq/commit-protocol`
- Production source commit:
`d25e689b0d5c681755751da257700f0d3f7974d1`
`53fb52f2d8d7c5a3636810501b740d859d5a2c14`
- Production source tree:
`5553aa58ab006c85000c5a2b106988da2b61f002`
`91c5f458dd77f7d38f0c8107f00eb15a74c3ce37`
- Vercel production deployment:
`dpl_Cwh63QydtcGyVD9MeZ7jrSo3A1QE`
`dpl_BvXSZgubPSzs3Z9cyck6eY5dzvDt`
- Served coordinator:
`0xEE21cCFF8f3755487f774BFd5Da9Ff51D5688581`
- GitHub Actions `Verification` run: `35140950751` — all jobs passed
- GitHub Actions `Verification` run: `35142284628` — all jobs passed

Production smoke checks and the exact served-bundle binding are recorded in
[`PRODUCTION_RELEASE_2026-09-16.md`](./PRODUCTION_RELEASE_2026-09-16.md).
Expand Down
7 changes: 5 additions & 2 deletions docs/EXTERNAL_DELIVERY_OBSERVATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@ and the finalized execution result is `FINISHED_WITH_ERROR`.
| `UNVERIFIED` | No child ID, malformed/ambiguous child set, unreadable child, mismatched recipient/value, unknown result, or RPC failure. | Show that delivery is unresolved; do not infer success or terminal non-delivery. |

The UI exposes an explicit `Observe child transaction` action and keeps the
parent claim ID plus exact amount in beneficiary-scoped browser storage. This
allows re-observation after navigation without a page reload or a new write.
parent claim ID, exact mission ID, beneficiary, and amount in beneficiary-scoped
browser storage. This allows re-observation after navigation without a page
reload or a new write. A record is shown only when both the mission and the
connected beneficiary match; switching wallets cannot surface another wallet's
claim observation.
Browser storage is only a convenience cache; it is not trusted contract state.

## What this intentionally does not claim
Expand Down
11 changes: 6 additions & 5 deletions docs/PRODUCTION_RELEASE_2026-09-16.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ canonical Vercel alias and the exact Studio Next coordinator it targets.
## Release identity

- Repository: `https://github.com/Manablaq/commit-protocol`
- Deployed application source commit: `d25e689b0d5c681755751da257700f0d3f7974d1`
- Deployed application source tree: `5553aa58ab006c85000c5a2b106988da2b61f002`
- Deployed application source commit: `53fb52f2d8d7c5a3636810501b740d859d5a2c14`
- Deployed application source tree: `91c5f458dd77f7d38f0c8107f00eb15a74c3ce37`
- Public application: `https://commit-protocol.vercel.app`
- Vercel project: `mr-albert-s-projects/commitprotocol-genlayer`
- Vercel production deployment: `dpl_Cwh63QydtcGyVD9MeZ7jrSo3A1QE`
- Vercel production deployment: `dpl_BvXSZgubPSzs3Z9cyck6eY5dzvDt`
- Deployment state: `READY` / `PRODUCTION`

The source commit and tree above are the exact release built and published by
the recorded Vercel deployment. The deployment includes the narrow-viewport
overflow fix certified by the browser E2E gate.
overflow fix and wallet-bound claim-observation fix certified by the browser
E2E gate and regression suite.

## Served contract binding

Expand Down Expand Up @@ -51,7 +52,7 @@ Read-only checks against `https://commit-protocol.vercel.app` passed:
client-side error
- deployed JavaScript bundle contains the certified coordinator anchor and the
strict `EXTERNAL MESSAGE OBSERVATION` claim surface
- GitHub Actions `Verification` run `35140950751` for the repository release:
- GitHub Actions `Verification` run `35142284628` for the application release:
completed successfully across Python, Direct Runtime, and frontend jobs

The verification API remains read-only. It does not reconstruct chain truth or
Expand Down
13 changes: 12 additions & 1 deletion lib/genlayer-delivery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ export type ExternalDeliveryExpectation = {
};

export type PersistedClaimTransaction = {
missionId: string;
beneficiary: `0x${string}`;
transactionId: TransactionHash;
amount: bigint;
};
Expand Down Expand Up @@ -356,7 +358,12 @@ export function readPersistedClaimTransaction(
const record = candidate as Record<string, unknown>;

if (
typeof record.transactionId !== "string"
typeof record.missionId !== "string"
|| typeof record.beneficiary !== "string"
|| !/^0x[0-9a-fA-F]{40}$/.test(record.beneficiary)
|| record.missionId !== missionId
|| record.beneficiary.toLowerCase() !== beneficiary.toLowerCase()
|| typeof record.transactionId !== "string"
|| !isTransactionHash(record.transactionId)
|| typeof record.amount !== "string"
|| !/^[1-9][0-9]*$/.test(record.amount)
Expand All @@ -365,6 +372,8 @@ export function readPersistedClaimTransaction(
}

return {
missionId: record.missionId,
beneficiary: record.beneficiary as `0x${string}`,
transactionId: record.transactionId,
amount: BigInt(record.amount),
};
Expand All @@ -387,6 +396,8 @@ export function persistClaimTransaction(
window.localStorage.setItem(
claimTransactionStorageKey(missionId, beneficiary),
JSON.stringify({
missionId,
beneficiary: beneficiary.toLowerCase(),
transactionId,
amount: amount.toString(),
}),
Expand Down
12 changes: 12 additions & 0 deletions tests/frontend/genlayer-delivery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,18 @@ describe(
expect(
readPersistedClaimTransaction(missionId, RECIPIENT)?.amount,
).toBe(AMOUNT);
expect(
readPersistedClaimTransaction(
"different-mission",
RECIPIENT,
),
).toBeNull();
expect(
readPersistedClaimTransaction(
missionId,
OTHER_RECIPIENT,
),
).toBeNull();
window.localStorage.setItem(
claimTransactionStorageKey(missionId, RECIPIENT),
"not-a-hash",
Expand Down
Loading