Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
7c7acd5
Publish Afterlight mainnet evidence
dolepee Aug 28, 2026
a426943
Publish deployed Afterlight mechanism
dolepee Aug 28, 2026
0c23470
Monitor the post-spike relayer state
dolepee Aug 28, 2026
94d9e42
Define the user-first recovery interface
dolepee Aug 28, 2026
e7bd2e8
Align client docs with mainnet evidence
dolepee Aug 28, 2026
5655e42
Link the verified mainnet release evidence
dolepee Aug 28, 2026
46cd481
Use accessible mainnet evidence links
dolepee Aug 28, 2026
0cb762c
Ship public Afterlight recovery product
dolepee Aug 28, 2026
af281a6
Install shared client dependencies in web CI
dolepee Aug 28, 2026
4fedd70
Bound public claim network sponsorship
dolepee Aug 28, 2026
bae3d2f
Use interactive Ready connection from connect button
dolepee Aug 28, 2026
93b8ecf
Make relayer rate-limit test deterministic
dolepee Aug 28, 2026
312ffa8
Reconcile ambiguous funding checkpoints onchain
dolepee Aug 28, 2026
2e5b9b0
Require a fresh funding checkpoint
dolepee Aug 28, 2026
4f48f4c
Rotate the bounded E3 relay ledger
dolepee Aug 28, 2026
fe14067
Wait for propagated relay receipts
dolepee Aug 28, 2026
7f0d680
Authorize the canonical Afterlight origin
dolepee Aug 28, 2026
fb918a7
Bound E3 sponsorship to the funded budget
dolepee Aug 28, 2026
1dd4a90
Classify private claim preflight stages
dolepee Aug 28, 2026
603b0d2
Use the canonical exit binding as budget key
dolepee Aug 28, 2026
af0b81d
Classify private claim estimate failures
dolepee Aug 28, 2026
ca90dc2
Use Starknet RPC codes for claim diagnostics
dolepee Aug 28, 2026
b5ab821
Use the audited STRK20 estimate envelope fallback
dolepee Aug 28, 2026
c60b78c
Align the claim cap with the proven resource reservation
dolepee Aug 28, 2026
d10aeec
Use the exact Starknet claim resource bounds
dolepee Aug 28, 2026
52463b3
Preserve private claim failure classification
dolepee Aug 28, 2026
628afdd
Publish canonical demo and production health checks
dolepee Aug 28, 2026
6cb2a15
Align Ready onboarding with the live public interface
dolepee Aug 28, 2026
d4be7ae
Separate claim signing from broadcast state
dolepee Aug 28, 2026
def6535
Add launch-ready metadata and social assets
dolepee Aug 28, 2026
9fc9288
Lead the repository with the live recovery product
dolepee Aug 28, 2026
01446bf
Meet touch targets across public navigation
dolepee Aug 28, 2026
17959fb
Test exact neutral exit signing boundary
dolepee Aug 28, 2026
8410b4d
Rotate stale claim sponsorship ledger
dolepee Aug 28, 2026
a2cdb27
Document safe sponsorship ledger recovery
dolepee Aug 28, 2026
d232afe
Classify exact claim broadcast failures
dolepee Aug 29, 2026
9517d67
Route private exits through the proven RPC
dolepee Aug 29, 2026
cf6510b
Publish public E3 recovery evidence
dolepee Aug 29, 2026
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
24 changes: 24 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,27 @@ jobs:
run: npm --prefix ../client ci
- run: npm run check
- run: npm audit --audit-level=high

web:
name: Public product gate
runs-on: ubuntu-latest
timeout-minutes: 10
defaults:
run:
working-directory: web
steps:
- name: Check out source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22.13.1
cache: npm
cache-dependency-path: web/package-lock.json

- run: npm ci
- name: Install shared client type dependencies
run: npm --prefix ../client ci
- run: npm run build
- run: npm audit --audit-level=high
16 changes: 9 additions & 7 deletions .github/workflows/relayer-health.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Inert relayer staging health
name: Post-spike relayer health

on:
schedule:
Expand All @@ -9,12 +9,12 @@ permissions:
contents: read

concurrency:
group: inert-relayer-health
group: afterlight-relayer-health
cancel-in-progress: true

jobs:
health:
name: Verify fail-closed staging
name: Verify production submission and privacy boundary
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
Expand All @@ -40,10 +40,12 @@ jobs:
.status == "ok" and
.service == "afterlight-neutral-relayer" and
.schema == "afterlight-relay/1" and
.submission == "disabled" and
.executor.configurationReady == false and
.executor.executable == false and
.balance.status == "disabled" and
.submission == "enabled" and
.executor.configurationReady == true and
.executor.signerAdapterAvailable == true and
.executor.executable == true and
.balance.status == "ok" and
.balance.alert == false and
.privacy.payloadLogging == false and
.privacy.appKeysHeld == false and
.privacy.walletAddressesRequired == false
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@ target/
.snfoundry_cache/
client/node_modules/
client/dist/
web/node_modules/
web/dist/
client/tools/ready-quote.js
client/tools/mainnet-operator.js
client/tools/declarer-funding.*
client/tools/quote-declarer-funding.mjs
client/tools/verify-declarer-funding.mjs
client/tools/mainnet-operator-config.local.json
client/tools/private-exit-preflight.js
client/tools/private-exit-preflight.meta.json
client/tools/successor-activation
private-ready-lifecycle
.DS_Store
*.log
.env
Expand Down
66 changes: 66 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
version: alpha
name: Afterlight
description: User-first interaction guidance for a private Starknet recovery reserve.
colors:
ink: "#191915"
muted: "#68685f"
paper: "#FFFDF8"
line: "#D8D3C8"
accent: "#D86F31"
accent-dark: "#8E3514"
soft: "#EBE6DB"
typography:
body:
fontFamily: Inter, ui-sans-serif, system-ui, sans-serif
headline:
fontFamily: Georgia, Times New Roman, serif
fontWeight: 500
lineHeight: 0.98
letterSpacing: -0.045em
omitted:
- section: spacing
reason: Layout spacing is evidenced, but no named shared spacing scale exists.
- section: rounded
reason: Repeated radii exist, but no named shared radius scale exists.
- section: components
reason: Shared component behavior is documented in prose without a token contract.
---

## Overview

Afterlight is an ordinary self-custody recovery product, not an evaluator surface. Lead with the useful result: create a bounded private recovery reserve, remain in control through heartbeat and veto, and let only the designated successor key authorize recovery after inactivity and grace. Keep STRK20 receipts and technical proof contextual to the action that produced them.

## Colors

Use warm paper and soft neutral surfaces to keep the recovery journey calm and legible. Ink carries primary text and actions; muted supports explanatory copy; the earthy accent identifies privacy guidance and selected controls without becoming a decorative gradient. Reserve distinct success and error treatments for state feedback, and never rely on color alone.

## Typography

Use the body family for controls, instructions, wallet state and receipts. Use the headline family only for the product promise and major journey titles; its restrained weight and tight setting establish hierarchy without turning operational screens into marketing pages.

## Layout

Use one role-aware application shell with separate owner and successor journeys. Show the current vault state, the next meaningful deadline, and one primary action before secondary controls or transaction details. Preserve the same reading order at mobile and desktop widths; wider layouts may place contextual status beside the action, but must not turn the journey into a dashboard grid.

Every remote or wallet-dependent region needs loading, empty, error, wrong-network, insufficient-balance, interrupted-flow, and reload-recovery states. The owner and successor journeys must remain usable at 320px, 768px, 1024px, and 1440px widths.

## Components

The unauthenticated primary action is “Create a recovery reserve.” Owner setup progressively reveals Ready X connection, reserve mode and denomination, inactivity and grace periods, the successor public key, recovery-package backup, and private funding. Do not expose later actions before their prerequisites are satisfied.

Vault status presents `ACTIVE`, `GRACE`, `CLAIMED`, or `CANCELLED` in plain language together with the relevant heartbeat, request, grace, or terminal outcome. Do not use color alone to distinguish states.

Owner controls expose heartbeat, veto, and private cancellation only when valid. Successor controls expose key generation, invitation import, request, exact destination-note preparation, and claim only when valid. Explain why an action is unavailable instead of leaving a dead control.

Wallet reviews must repeat the expected role, network, token, amount, privacy consequence, and fee boundary immediately before confirmation. After an action, show the useful result first and place its receipt, contract address, and transaction hash in a contextual expandable region.

The privacy boundary belongs near reserve creation and recovery confirmation. State what remains public—contract, token, denomination, timing, application public keys, and state transitions—and what STRK20 keeps unlinked for public observers. Never describe Afterlight as automatic legal inheritance.

Interactive controls use native elements, visible labels, visible keyboard focus, reduced-motion-safe feedback, and touch targets at least 44px in both dimensions. Dialogs and wallet-return flows restore focus to the action that opened them, and status changes are announced without moving focus unexpectedly.

## Do's and Don'ts

Use outcome-first copy, ordinary wallet language, and contextual receipts. Make heartbeat, inactivity, grace, veto, cancellation, and exact private recovery understandable without requiring contract terminology.

Do not add “Judge,” “Judging,” “Proof,” or “Evidence” primary navigation. Do not lead with raw hashes, architecture, a generic explorer, or a separate evaluator dashboard. Do not create a one-use demo path that cannot recover after reload or an interrupted Ready X flow. Do not imply hidden amounts, hidden timing, invisible authorization keys, proof that a note belongs to a precommitted wallet, or legal inheritance guarantees.
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ Afterlight is a private, bounded recovery reserve for Starknet self-custody wall

An owner privately funds a fixed reserve through STRK20 and remains in control through authenticated heartbeats and a veto window. If no authenticated heartbeat arrives during the configured interval, only the designated successor application key can authorize recovery to one exact private destination after the grace period.

[Open Afterlight](https://afterlight.dolepee.com) · [Mainnet evidence](docs/MAINNET.md) · [Deployed contract](https://starkscan.co/contract/0x06e8b6e49b4366e0dc6a35eee722b417c718988eca3f4a0c298bdf8785261c25)

[![CI](https://github.com/dolepee/afterlight/actions/workflows/ci.yml/badge.svg)](https://github.com/dolepee/afterlight/actions/workflows/ci.yml)

## Current status

**Evidence level: E1 (locally repeatable implementation evidence).** The recovery contract, application-key client, structural prepared-exit envelope validator, and neutral-relayer boundary have deterministic local test and build coverage. The locked deployment artifacts also reproduce locally.
**Evidence level: E3 public completion.** The complete recovery mechanism has run through the deployed public app on Starknet Mainnet. Five successful transactions touch both the canonical STRK20 pool and Afterlight. The fresh public Recovery Drill completed private funding, heartbeat, request, veto, a second request, and [exact-note recovery](https://voyager.online/tx/0x722033f7fd0397ff4d3845428c98cad885b6a63824f7c78a2b7e1d7d6f5c1b6); Ready X then showed the successor's shielded balance increase from `7 STRK` to `8 STRK` while the neutral sponsor paid the pool and network fees.

**Release status: pre-deployment and not user-ready.** The Afterlight class and contract are not declared or deployed, no funded mainnet lifecycle has run, no qualifying transaction hashes exist, and no E2 mainnet result is claimed. The public relayer endpoint is an inert, submission-disabled packaging and health check; it is not a live recovery service.
**Release status: deployed public Mainnet product.** Afterlight is [deployed on Mainnet](https://starkscan.co/contract/0x06e8b6e49b4366e0dc6a35eee722b417c718988eca3f4a0c298bdf8785261c25). The bounded neutral relayer executed the public control and recovery path without using either Ready role as the outer sender. The public app supports real Ready X connection, local per-vault keys, private funding, live state, relayed controls, exact-note recovery, contextual receipts, and post-claim balance reconciliation.

## Recovery flow

Expand Down Expand Up @@ -39,10 +43,11 @@ Afterlight does not claim legal inheritance, invisible authorization keys, proof
- `tests/` — Cairo unit and integration tests
- `client/` — application keys, typed authorization messages, Ready/STRK20 action assembly
- `relayer/` — fail-closed neutral-relayer implementation and operational controls
- `web/` — user-first owner and successor journeys for the deployed Mainnet release
- `docs/ARCHITECTURE.md` — component boundaries, action routing, state and accounting model
- `docs/THREAT_MODEL.md` — protected assets, trust assumptions, privacy limits, and failure handling
- `docs/READY_X_ONBOARDING.md` — pre-deployment Ready X prerequisites and planned owner/successor flow
- `docs/MAINNET.md` — pinned Mainnet dependencies, locked artifacts, and intentionally empty evidence slots
- `docs/READY_X_ONBOARDING.md` — Ready X prerequisites and owner/successor flow
- `docs/MAINNET.md` — pinned Mainnet dependencies, deployed artifacts, and transaction evidence

## Design documentation

Expand Down Expand Up @@ -74,13 +79,16 @@ npm --prefix client test

npm --prefix relayer ci
npm --prefix relayer run check

npm --prefix web ci
npm --prefix web run build
```

The public CI workflow also rebuilds the locked `spike-inline-56` deployment
profile and verifies its exact Sierra and compiled class hashes before running
the Cairo, client, and relayer tests. It audits both npm trees, checks relayer
types and lint rules, and builds a submission-disabled Cloudflare Worker dry
run.
the Cairo, client, relayer, and web checks. It audits every npm tree, checks
relayer types and lint rules, builds both Worker configurations without
submitting, and compiles the production web bundle.

No wallet seed, application private key, or relayer secret belongs in source control. The relayer remains unable to submit transactions unless its complete production configuration is installed and its explicit submission switch is enabled.

Expand Down
30 changes: 19 additions & 11 deletions client/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# Afterlight client and local operator primitives (E1)
# Afterlight client and local operator primitives

This package contains deterministic application-key, authorization, relay-schema,
STRK20 action, structural prepared-exit envelope validation, read-only quote, and explicit local
operator primitives. It has no public product UI or production storage. Its
quote, preflight, and operator tools can read Mainnet; only the explicitly labelled
operator buttons can request a wallet declaration or deployment, and each still
requires a visible Ready X confirmation. No mainnet deployment is claimed.
requires a visible Ready X confirmation. The deployed Mainnet release and its
four qualifying receipts are recorded in [`../docs/MAINNET.md`](../docs/MAINNET.md).

```sh
npm ci
Expand All @@ -17,10 +18,10 @@ The tested toolchain is Node.js `22.13.1` with the committed npm lockfile.
The live exit canary is intentionally strict: `CANCEL_REFUND` and `CLAIM` give
Ready exactly an `OPEN` transfer followed by the helper invoke. They never add a
public self-withdraw. Ready adds its own private paymaster-fee withdrawal during
submission. A successful mainnet Wrenchless claim demonstrates this app-action
shape ([source](https://github.com/Timidan/wrenchless/blob/b61e989ad9f24d9ba4803bf28b796564579bd220/packages/canary-core/src/refill-claim.ts),
[mainnet receipt](https://voyager.online/tx/0x02e969f712d5ff8f3091bd42b06978c285c8ad221081da5f575afbc72f87888e)),
but Afterlight must still reproduce it with its own helper before promotion.
submission. Afterlight reproduced this exact-note route through its own helper
for both `CANCEL_REFUND` and `CLAIM` on Mainnet. The contract states, liability,
pool allowance, exact destination notes, and four qualifying receipts reconcile;
Ready's wallet-visible post-exit balance remains the final E2 visibility check.

Application secrets are held by `LocalStarkKey`; ordinary serialization exposes only the public key. Raw secret export requires the explicitly named backup method and confirmation constant. Relayer requests contain only signed public calldata for `HEARTBEAT`, `REQUEST`, or `VETO`.

Expand All @@ -33,6 +34,13 @@ only to the alternative route where a dApp/paymaster submits the exact
Ready `wallet_strk20InvokeTransaction`, which accepts actions and generates a
separate fee-bearing proof.

`assertManagedReadyExitEvidence` is the independent post-receipt gate for that
normal Ready route. It parses the actual outer transaction, rejects either
Ready role account as sender, locks the observed Ready sponsor
forwarder/selector, exact pool call, signed note and Afterlight calldata, and
then requires a succeeded receipt plus exact reserve-minus-fee shielded-balance
and liability deltas. A prepared action or wallet review cannot satisfy it.

The mainnet quote tool is simulation-only. It has no signing or submission
method. Build the selected Scarb profile first, then set a deployed public
account as the intended deployer to derive its exact UDC address:
Expand All @@ -45,9 +53,9 @@ AFTERLIGHT_SIMULATION_SENDER=0x... \
npm run quote:mainnet
```

`AFTERLIGHT_SURPLUS_ADMIN` defaults to that same public address and may be set
separately. The tool prints the full constructor calldata so the eventual
wallet review can be reconciled field-for-field.
The tool prints the full constructor calldata so the eventual wallet review can
be reconciled field-for-field. The contract has no surplus administrator or
administrative withdrawal path.

## Local mainnet operator

Expand All @@ -56,7 +64,7 @@ deployment operator. It does not auto-sign or auto-submit. Before enabling its
two wallet-impacting buttons it recomputes the Sierra and CASM hashes, derives
the exact UDC address, verifies Mainnet, checks the intended deployer, and reads
whether the class and contract already exist. Once deployed, the same read-only
refresh fails closed unless Mainnet returns the locked class hash and all eleven
refresh fails closed unless Mainnet returns the locked class hash and all ten
constructor-derived configuration fields exactly.

Copy `tools/mainnet-operator-config.example.json` to the ignored
Expand All @@ -74,7 +82,7 @@ separate, visible Ready wallet confirmation.

## Local private-exit preflight

`tools/private-exit-preflight.html` is an E1-only, no-submit check for
`tools/private-exit-preflight.html` is a no-submit structural check for
`CANCEL_REFUND` and `CLAIM`. It reads the currently selected Ready account
directly and silently before and after each Prepare call, enforces the
operation's plausible state/epoch/nonce and 900-second authorization window,
Expand Down
Loading