Skip to content

Capstone: finish with a real wallet you can receive to (no real sats) #89

Description

@Jolah1

The Open Source path graduates on something real: a merged PR, verified against the GitHub API. The money side of the curriculum has no equivalent. A learner can finish every flight path without ever having installed a Bitcoin wallet of their own.

Proposal: a capstone mission where the learner sets up a real wallet and proves it works.

Scope, decided up front

No real sats. We are not running a faucet, not distributing sats, and not integrating a service that gives them away. A sats source has to survive being drained by the first person who finds the endpoint, needs a rate limit, and needs a story for the day it runs dry. None of that teaches anything, and all of it can go wrong in public.

Custodial is fine, and is the point. A beginner with a working custodial wallet has learned more than one who bounced off seed-phrase ceremony and gave up. The self-custody path is where that graduation happens, and it already exists.

So the mission is: install a real wallet, and prove you can receive with it. Nothing moves.

Proof, without moving money

Two workable shapes, both checkable server-side:

  1. Paste an invoice from your own wallet. Ask for a BOLT-11 invoice for a specific amount. Decode it server-side, confirm it parses, confirm the amount matches what we asked, and confirm it is not one we issued. That proves a real wallet exists and can generate a receive request. Nothing is ever paid.
  2. Paste your Lightning address. Resolve its LNURL-pay endpoint and confirm it exists and is payable. Smaller and friendlier, and it reuses the resolution logic proposed for mission 38 in Lightning: 2 of 12 missions have a hands-on step #83.

Either works. (1) is stronger evidence of a working wallet, (2) is less to type on a phone.

Which wallet

Do not name one wallet. An endorsement in curriculum copy ages badly and puts us in the position of vouching for a custodian. Offer three or four current custodial options and let the learner pick. The comparison is itself the lesson, and it pays off mission 10 (custodial vs self-custodial) with a real decision instead of a quiz answer.

The migration problem, which is the hard part

Adding a mission to an existing flight path silently un-earns that path's badge for everyone who already completed it.

Badge::all_for in backend/src/models/badge.rs derives badges live from the completion ledger:

let required = mission_ids.len() as u8;
let earned = required > 0 && completed >= required;

required is computed from current tree membership, every time it is read. Add a fourteenth mission to a twelve-mission path and every learner sitting at 12 of 12 drops to 12 of 13, and their badge reverts from earned to unearned. Their completions are safe, and any certificate already issued is stored and stays valid, but the badge they earned disappears from the UI.

This is worth getting right rather than discovering after the fact. Options:

  • Put the capstone in its own place rather than inside an existing path, so no path's required count changes.
  • Accept the reversion, if the affected cohort is small enough to be worth it. Check the numbers before assuming.
  • Freeze earned badges by recording the earn once instead of deriving it live. This is a real design change, and the current derive-on-read approach is deliberate (the doc comment notes it means "no drift, no migration when tree membership shifts"), so do not do this casually.

Whoever picks this up: decide this first, before writing mission copy. Related context in #76.

Notes

  • Mission membership is mirrored: Tree::from_mission in backend/src/models/mission.rs is the source of truth, TREES in frontend/src/lib/types.ts mirrors it. Both must agree, and Mission::LAST moves when you add one.
  • A Lightning address is a semi-identifying handle and proofs are stored permanently in mission_completions. Prefer the invoice shape if that concerns you, and do not ask for anything more identifying than the proof requires.
  • See Curriculum: 91 of 106 missions end at a quiz #76 for the four-step guide to adding a new DoKind.

Metadata

Metadata

Assignees

No one assigned

    Labels

    curriculumMission content: lessons, quizzes, hands-on stepsenhancementNew feature or requesthelp wantedExtra attention is needed

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions