Cashvy Not out yet

The bridge

How a friend joins a trip.

Cashvy has two halves: the app, on the phone of whoever keeps the trip, and a web page for everybody else. This is how they meet, and what each one is allowed to do.

Joining a trip from a browser, in five steps

  1. The host makes a code for one person

    In the trip, the host taps Share this trip and picks who the code is for. Cashvy draws a QR code and makes a link. The code works once, for one browser, and stops working after fifteen minutes if nobody uses it.

    The Share this trip screen, listing Ana, Maya and Sam, each with a Make a code button, and an empty list of browsers let in so far.
  2. You open it, in any browser

    Point your camera at the code, or open the link you were sent. It opens join.cashvy.app — a web page, not an app. No download, no account, no email address, on a phone or a laptop.

    If somebody sent you the link and you ended up here instead, paste it into the box on the homepage.

    https://join.cashvy.app/#v1.4fQ…k2w.9Xb…

    The address your browser asks for

    The key — browsers never send anything after the #

    Drawn for this page. A real link is about 110 characters long.
  3. You both read six words aloud

    Your screen and the host’s show the same six words. If they match, the host taps Same words and you are in. If they do not match, stop there and tell the host: something is sitting between your browser and their phone.

    That check is what makes it safe for the connection to pass through a relay: it would take a person, not a computer, to be fooled.

    Example words, drawn for this page.
  4. You read the trip and add what you paid

    Your browser keeps a copy of the trip’s ledger. Anything you add arrives on the host’s phone as an unfiled slip — yellow, with a torn top edge — until somebody with the app decides it.

    The Lisbon trip ledger, showing your position and a list of expenses, two of them on yellow slips marked unfiled, from the browser, with Decline and Approve buttons.
  5. Somebody with the app files it

    Approving, declining and settling up happen on a phone with Cashvy, never in the browser. When the host files your expense, your copy shows it filed too.

    The homepage has a stamp you can press that plays this part out.

    The Activity tab, “2 waiting on you”: two yellow unfiled slips added from the browser — a tuk-tuk tour and wine for the flat — each with Decline and Approve.

The rules, not a summary of them

What a browser can do, and what it cannot.

The host’s phone checks every request a browser sends against these lists, and a test in Cashvy’s source fails if this page and the rules ever disagree.

A browser may

  • Read the trip’s ledger
  • Add what you paid
  • Attach a receipt photo to an expense you paid allowed; not in the web page yet
  • Pick your own character

And only as itself. A browser can add an expense only as the person who paid it, and change only its own character — never somebody else’s row. The same rules would let it rename itself and claim its own lines on a scanned receipt; the web page has no controls for either yet.

Only the app may

  • Approve an expense, or void one
  • Decline an expense
  • Record a payment between two people
  • Confirm or dispute a payment
  • Attach proof that a payment was made
  • Add people, start trips, and make join codes
  • Remove someone from a trip
  • Archive a trip
  • Save someone’s payment handle
  • Remove a payment handle
  • Use a photo as someone’s picture
  • Record a loan between two people, outside any trip
  • Cancel a loan
  • Attach proof to a loan

Hiding a button is not what stops a browser. The browser is somebody else’s machine, so Cashvy assumes it could send anything at all — and the host’s phone refuses what the rules do not allow, whatever arrives.

The details

When the host’s phone is away

Your browser keeps the last copy of the trip it saw, so you can still read it when the host’s phone is off or out of signal, and the page tells you how old that copy is. Anything you add waits in the tab and is sent the moment the phone is back.

Waiting items are lost if you close the tab. A closed tab cannot come back into the same session, so an outbox kept on disk could never be sent — it would only look like it was waiting.

The link is the key

Everything after the # in a trip link is the part browsers never send anywhere — not to join.cashvy.app, not to us, not to anybody. That is where the key to the trip lives.

Your browser and the host’s phone lock everything they say to each other using that key plus two fresh keys that never appear in the link. So someone who photographs the code could use it to join — which is why it works once, expires, and the host sees every browser that used it and can turn each one off — but they cannot read a trip they did not join. The link is only half of what it takes.

How the messages travel

Your browser and the host’s phone need an introduction first, and that goes through a relay — as sealed messages the relay cannot read. After that they try to reach each other directly: on the same wifi the trip itself need never leave the network. Only if a direct connection is impossible does the relay carry the whole conversation, still sealed. The host’s screen says which of those actually happened, not which one was attempted.

The relay keeps nothing once a connection closes and needs no account. The one Cashvy uses by default is ours, and it is not free to run: the traffic it carries when two devices cannot reach each other is Cashvy’s only real running cost. Anyone who would rather not use it can run their own from the same source.

Phone to phone, with no internet

Two phones with Cashvy can pass a whole trip between them as a file, over AirDrop, or by radio alone with Hand it to a phone nearby. The file is signed by the phone that made it, and nothing is added to your ledger until you have seen what is in it and said yes.

While a phone is looking for others nearby, it announces two random words and a version number, and nothing else — not your name, not the trip, not anything that stays the same from one day to the next.