Subsystem

Part 3 of 6 Watching and steering in a browser

Signed in, from a browser or a phone

By the end of this chapter, Keanu is working in his team's Subroutine from his own browser, having installed nothing, and the same address is an app on his phone.

This is the way in that asks least of you. Somebody else runs the instance; you are given an address and a link, and you are in.

The work so far

Laurence has an instance on a server, serving at https://tasks.example.com, with a workspace called metacortex for the team's work. Running one for other people comes later in this guide, and does it properly: an account of its own, a proxy in front, and a service manager to keep it up. These are the fewest commands that get to the same place:

$ uv tool install subroutine
Resolved … packages in …
Prepared … packages in …
Installed … packages in …
…
Installed 2 executables: subr, subroutine
$ subroutine init --workspace metacortex --instance-name MetaCortex
Ready. Try: subroutine add "something to do"
$ printf 'public_url = "https://tasks.example.com"\n' >> ~/.config/subroutine/config.toml
$ subroutine serve
Serving on http://127.0.0.1:8471

What to ask for

The address, which is all a browser needs. https://tasks.example.com here.

A token, if you are also going to use a terminal or point an agent at the instance. It is a different credential for a different door, and the next two chapters use it.

The workspace, if the instance holds more than one. Most hold one and you will never hear the word.

There is nothing to create on your side, no key to exchange, and no configuration file to write.

An account, and the way in

One command makes the account and hands over the ways in. Laurence runs it:

$ subroutine user create keanu --name "Keanu Reeves" --browser --terminal | tee /tmp/for-keanu
Created keanu
keanu is now member in metacortex
Local commands will go on acting as laurence.

A sign-in link for keanu, good for the next 30 minutes.

https://tasks.example.com/signin?link=sr_lnk_…

That is the only time it is shown, and it works once.

A credential for keanu, for the command line.

sr_…

That is the only time it is shown. Nothing recovers it afterwards.
…

| tee /tmp/for-keanu keeps a copy of what it printed. Send that to Keanu however you would send anything private: the link signs in as him, and the token acts as him.

Signing in

Keanu has the message and no Subroutine at all. Opening the link in a browser is the whole of it, and the browser is then signed in.

The lines below are Keanu's, and they take the message out of that file, which stands in for whatever it was actually sent in:

$ instance=https://tasks.example.com
$ link=$(grep -o "$instance/signin?link=[^ ]*" /tmp/for-keanu)
$ curl -so /dev/null -w '%{http_code}\n' "$link"
303

303 is the instance taking the link, signing the browser in and sending it on to the page. In a browser you see none of that: you paste the address and your work is there.

A token will not open a browser

The other credential in that message is for a terminal. Putting it where the link goes does not sign anything in:

$ token=$(grep -o 'sr_[A-Za-z0-9_-]*' /tmp/for-keanu | tail -1)
$ curl -so /dev/null -w '%{http_code}\n' "$instance/signin?link=$token"
401

They are different credentials for different doors, and having one does not get you the other. If a browser will not let you in, it is a link you need, and asking for another costs nothing.

What is there

The agenda, the list and the board, as Watch it happen describes them: your work, everything in the workspace, an item in full, and a box that takes a new task.

The page is drawn from what your account may do. Where you may not write, the controls for writing are absent rather than present and refused: no capture box, no Complete, no Edit, no comment box. That is a role rather than a fault, and whoever set you up can change it.

A screen that only reads

That is also how an instance is put on a wall. A viewer account reads and does nothing else:

$ subroutine user create screen --name "Office screen" --role viewer --terminal | tee /tmp/for-screen
Created screen
screen is now viewer in metacortex
…
sr_…
…

A role holds at every door, not only in the page. Here is one request made twice, with Keanu's credential and then with the screen's:

$ new='{"text":"Order a new phone for reception"}'
$ mine="Authorization: Bearer $token"
$ wall="Authorization: Bearer $(grep -o 'sr_[A-Za-z0-9_-]*' /tmp/for-screen | tail -1)"
$ curl -so /dev/null -w 'keanu %{http_code}\n' -H "$mine" --json "$new" $instance/v1/tasks
keanu 201
$ curl -so /dev/null -w 'screen %{http_code}\n' -H "$wall" --json "$new" $instance/v1/tasks
screen 403

So the page is not hiding a button that would have worked: the instance refuses the write underneath it.

On your phone

The same address installs as an app, with an icon of its own, a window with no address bar, and a place in the app switcher. There is nothing to download from a store.

What makes that possible is served by the instance itself, and it carries the address:

$ curl -s $instance/app/manifest.webmanifest
…
        "name": "Subroutine (tasks.example.com)",
        "short_name": "tasks.example.com",
…

That name is what the icon is called, and it carries the address because that is what tells two of them apart on one home screen.

The rest is your browser's own, and differs between them:

  1. Sign in first, in the browser you want the app in. Paste the link rather than tapping it, because a tapped link opens in whichever browser the device treats as the default, and the link is spent by whichever opens it.
  2. Check your work is there. The app inherits that browser's session.
  3. Install it from the browser's own menu, where it is called Install, Install app or Add to Home Screen. It is never a control on the page.
  4. Open it from the home screen. It comes up signed in.

If your browser's menu offers nothing, try another one: browsers differ about when they will install a page and what they make when they do. Nothing is stored on the device either way, so it needs the network exactly as the page does.

Use a browser that keeps its cookies. Anything that erases them when you leave needs a fresh link every time.

Signing out

Sign out is in the menu under your name, and it ends that browser. Removing the icon from a home screen signs nothing out.

Whoever runs the instance can end it for you, on every browser at once, which is what a lost phone needs:

$ subroutine login revoke keanu
Signed keanu out of 1 browser, and spent any unused links.

That leaves his token alone: subroutine token revoke is the one for the other door.