Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
491bda7
Harden recovery sponsor and refine public journey
dolepee Aug 29, 2026
3bd52cd
Complete reserve modes and private cancellation
dolepee Aug 29, 2026
16c7e13
Resolve exact-head sponsor review findings
dolepee Aug 29, 2026
a1ab105
Make sponsor capacity fresh and ledger aware
dolepee Aug 29, 2026
cafd4df
Include control nonce activity in exit capacity
dolepee Aug 29, 2026
85e5ec4
Close sponsor concurrency and reconciliation gaps
dolepee Aug 29, 2026
33491d5
Persist recoverable exit hash before broadcast
dolepee Aug 29, 2026
63bc4e2
Close sponsor admission and rebroadcast crash windows
dolepee Aug 29, 2026
f301c16
Keep recovery journey first on mobile
dolepee Aug 29, 2026
262ec2d
Fail closed on unparseable exit receipt fees
dolepee Aug 29, 2026
e054fe0
State sponsor capacity boundary truthfully
dolepee Aug 29, 2026
93fbb2a
Reject non-FRI exit receipt fees
dolepee Aug 29, 2026
34912e6
Require explicit FRI receipt units
dolepee Aug 29, 2026
c14e8e8
Recover crash-safe relayer submissions
dolepee Aug 29, 2026
18cf0e8
Fence hashless reservation takeovers
dolepee Aug 29, 2026
3af720a
Bind checkpoints to funding admission owner
dolepee Aug 29, 2026
d5e9abe
Close relay recovery gaps and tighten journeys
dolepee Aug 29, 2026
b417d23
Fence checkpoint retry ownership
dolepee Aug 29, 2026
3625810
Align relayer recovery runbook
dolepee Aug 29, 2026
9a64fbf
Harden exact retry reconciliation
dolepee Aug 29, 2026
e61be57
Make recovery onboarding resilient
dolepee Aug 29, 2026
81da0d1
Harden public release metadata
dolepee Aug 29, 2026
ccb9fec
Close recovery retry dead ends
dolepee Aug 29, 2026
12e4366
Keep security metadata standards compliant
dolepee Aug 29, 2026
7c0b822
Retain admitted checkpoint retries
dolepee Aug 29, 2026
89b02ac
Preserve hashless relay reconciliation
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
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -143,5 +143,6 @@ jobs:
- run: npm ci
- name: Install shared client type dependencies
run: npm --prefix ../client ci
- run: npm test
- run: npm run build
- run: npm audit --audit-level=high
38 changes: 25 additions & 13 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,18 @@ colors:
muted: "#68685f"
paper: "#FFFDF8"
line: "#D8D3C8"
accent: "#D86F31"
accent-dark: "#8E3514"
accent: "#C8642F"
accent-dark: "#843515"
soft: "#EBE6DB"
spacing:
compact: "8px"
control: "16px"
panel: "24px"
section: "48px"
rounded:
control: "7px"
panel: "12px"
shell: "18px"
typography:
body:
fontFamily: Inter, ui-sans-serif, system-ui, sans-serif
Expand All @@ -18,13 +27,10 @@ typography:
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.
components:
journeyProgress: "Three concise role-specific stages with complete, current and upcoming states."
activityBanner: "Inline wallet/network/action status; never overlays the vault or primary action."
liveState: "Outcome-first state block with one valid primary action and contextual metrics."
---

## Overview
Expand All @@ -41,24 +47,30 @@ Use the body family for controls, instructions, wallet state and receipts. Use t

## 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.
Use one role-aware application shell with separate owner and successor journeys. Begin each role with a three-stage progress strip and 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.

Use the compact, control, panel and section spacing values as an optical rhythm rather than a rigid mathematical grid. Controls use the tight radius, nested panels use the middle radius, and the main journey shell uses the softest radius with one tighter corner to give Afterlight a recognizable silhouette.

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.
The unauthenticated primary action is “Create a recovery reserve.” Owner setup progressively reveals Ready X connection, realistic `NORMAL` timing or clearly labelled `FAST_DEMO` timing, denomination, 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. Pair the machine state with a human result such as “Reserve protected,” “Owner still has control,” or “Recovery complete.” Do not use color alone to distinguish states.

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.
When an invitation validates, collapse its raw JSON into a compact summary of vault, reserve and timing. Keep replacement available through progressive disclosure. Never make raw JSON the largest element in a successful journey.

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.
Owner controls expose heartbeat, veto, and exact-note private cancellation only when valid. Cancellation requires an explicit irreversible-action confirmation and the restored owner key. 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.

Wallet, network and transaction feedback appears in the inline activity banner immediately above the journey. It must not float over or conceal a state, action, receipt or privacy explanation.

## 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.
Expand Down
15 changes: 15 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Security policy

Please report suspected vulnerabilities privately through
[GitHub's security-advisory form](https://github.com/dolepee/afterlight/security/advisories/new).
Do not open a public issue for an undisclosed vulnerability and do not include
wallet seeds, private keys, application-key backups, proof material, or other
secrets in a report.

Include the affected release or commit, impact, reproduction conditions, and
the smallest safe proof needed to understand the issue. Reports are reviewed on
a best-effort basis; this repository does not promise a bounty or response SLA.

Only the current public Mainnet release is in scope. Third-party wallet,
STRK20, RPC, Cloudflare, Starknet, and browser vulnerabilities should also be
reported to their respective maintainers when appropriate.
22 changes: 18 additions & 4 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,28 @@ Afterlight separates private value movement, application authorization, and tran
| Ready X and STRK20 | Shielded balances, private invocation, proof preparation, and exact open-note settlement | Owner or successor application secrets outside the user's device |
| Afterlight Cairo contract | Vault state, signed authorization, liabilities, timing, exact-note binding, and terminal settlement | Ready wallet identity assumptions |
| Client library | Per-vault key generation, typed authorization hashes, STRK20 action assembly, proof-envelope/call binding, and independent managed-exit receipt reconciliation | Relayer account key |
| Neutral relayer | Submit bounded `HEARTBEAT`, `REQUEST`, `VETO`, checkpoints, and strictly validated exact-note claim packages from one neutral account | Owner/successor secrets, Ready addresses, or authority over contract state |
| Neutral relayer | Submit bounded `HEARTBEAT`, `REQUEST`, `VETO`, checkpoints, and strictly validated exact-note claim/cancellation packages from one neutral account | Owner/successor secrets, Ready addresses, or authority over contract state |

## Action routing

`FUND`, `CANCEL_REFUND`, and `CLAIM` enter through the canonical STRK20 pool and the contract's `privacy_invoke` entrypoint. The contract rejects any other caller.

`HEARTBEAT`, `REQUEST`, and `VETO` are public state transitions authorized by per-vault Stark signatures. Any submitter may relay a valid authorization; the submitter is never the authority.

For a public claim, Ready creates the exact OPEN note and proof locally. The
successor application key binds that literal note to the current vault, epoch,
nonce, token and amount. A neutral sponsor accepts only the locked pool call,
For a private exit, Ready creates the exact OPEN note and proof locally. The
successor application key binds a claim—or the owner application key binds a
cancellation—to that literal note, current vault, epoch, nonce, token and
amount. A neutral sponsor accepts only the locked pool call,
proof facts, application signature, live state, exact allowance and bounded
resource quote, then signs and broadcasts the outer transaction once. The
contract and pool remain authoritative; package preparation alone is not
execution evidence.

The sponsor independently pins the live STRK20 pool class and permits exactly
`WriteOnce`, `EmitOpenNoteCreated`, then `Invoke`. The first action must write
the canonical packed token value to the storage key derived from the signed
destination note. Extra actions or writes fail before signing.

```text
Ready X + STRK20 pool
|-- FUND ------------------------------> Afterlight liability + ACTIVE vault
Expand Down Expand Up @@ -71,6 +77,14 @@ held token balance >= existing locked liabilities + new fixed reserve

Only the configured reserve becomes a vault liability. Donated surplus neither blocks funding nor creates a claim. Claim and cancellation reduce the liability exactly once; failed settlement reverts the state change.

The public product also reads the sponsor's collapsed claim-capacity status.
It disables new funding unless total liability is zero and one claim or cancellation is covered by the exact pool allowance,
the bounded outer fee, and the post-spend health floor. The supported public route serializes one funding admission at a time. This is an availability
guard, not an onchain authorization or per-vault capacity reservation: the deployed contract intentionally permits anyone to refresh its one-shot
checkpoint, and multiple fully collateralized vault liabilities may exist. A caller bypassing the supported route cannot consume another vault's
backing, but neither that caller nor an ordinary user is promised immediate neutral-sponsor capacity at a future exit. Claim and cancellation fail
closed and may wait until the operator restores the exact allowance, balance, and daily budget. The contract and pool remain final.

There is no administrative withdrawal path. Accidental donations remain
unaccounted surplus: they cannot create a vault claim, block a user action, or
change the exact locked liability. Donors should not expect protocol-level
Expand Down
17 changes: 11 additions & 6 deletions docs/READY_X_ONBOARDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

This is the Ready X flow implemented by the public Afterlight interface and
exercised by the deployed Mainnet mechanism. The contract and a complete
founder-operated lifecycle exist. The public interface is live, while a fresh
end-to-end E3 completion through that interface and unrelated-user E4
completion remain pending. Nothing in this document is a standing instruction
to fund or sign; users must review the live wallet request and current fees.
founder-operated E3 lifecycle through the public interface exist. An unrelated
owner-successor E4 completion remains pending. Nothing in this document is a
standing instruction to fund or sign; users must review the live wallet request
and current fees.

## Accounts and STRK20 prerequisites

Expand All @@ -27,6 +27,11 @@ then-current account, registration, protocol-fee, and gas route. Fees and
account state must be freshly quoted in Ready X; this document deliberately
does not present an old estimate as a funding instruction.

The public app requires Ready X `5.33.9` or a later compatible Ready `5.x`
release and verifies the Wallet API capabilities it uses. An incompatible
major release fails closed with the detected version instead of silently
attempting a transaction.

Keep the Ready account key, the Afterlight application key, and destination
note material separate. Never paste a Ready seed or private key into Afterlight,
the relayer, a repository, or an evidence file.
Expand All @@ -47,8 +52,8 @@ The current client library can export a key only through the explicit
That JSON contains the application private key and is **not encrypted by the
library**. Treat it like a signing secret: encrypt it with a user-controlled
method, store it offline, test restoration before funding, and never upload it
to the relayer. A production UI must make backup/import and this plaintext
library boundary explicit.
to the relayer. The public UI labels this plaintext boundary and requires a
successful local restore before it enables funding.

## Owner journey

Expand Down
6 changes: 5 additions & 1 deletion docs/THREAT_MODEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ Relayer availability is operationally important but not trusted for correctness.
| Owner veto races a mature claim | First valid included transition wins; the other sees changed state |
| Failed token/pool settlement leaves false state | Cairo transaction rollback restores state and liability |
| Tokens are donated directly to the helper | No administrative withdrawal exists; donated surplus remains inert and cannot change locked liabilities |
| Relayer drains sponsorship | Schema limits, expiry, rate limits, per-call cap, daily budget, nonce serialization, and breach freeze |
| Relayer drains sponsorship | Schema limits, expiry, validation before scarce per-vault rate limiting, separate control/exit daily caps, shared nonce serialization, and breach freeze |
| Prepared proof swaps the pool implementation or adds actions | Pinned live pool class plus an exact `WriteOnce → EmitOpenNoteCreated → Invoke` action sequence and canonical destination-note storage write |
| Ambiguous broadcast is retried or released | `SUBMITTED` retains its hash and reservation; duplicate/unknown RPC results reconcile without signing or rebroadcasting |
| Browser reload loses the only exact retry artifact | The opaque checkpoint admission owner and any ambiguous exact cancellation/claim package are retained in tab-scoped session storage until terminal reconciliation; exact-exit packages are privacy-sensitive but contain no owner or successor application secret and are never sent to logs or analytics |
| Reserve demand exceeds current neutral-sponsor capacity | The supported UI and checkpoint route fail closed unless live allowance, balance, exit cap, health floor, liability and lease state reconcile. The permissionless contract checkpoint can still admit another fully backed vault outside that route, so sponsorship is explicitly capacity-limited and an exit may queue until capacity is restored; no vault can consume another vault's backing. |
| Application logs correlate a wallet or vault | Request bodies, signatures, IPs, wallet addresses, vault IDs, and fingerprints are excluded from application logs; infrastructure metadata remains a separate limit |

## Relayer and hosting metadata boundary
Expand Down
Loading