Description
With the account store sorted, next up is the session store which once normalised will look as follows with an optional reference to the accounts table since a session might be linked to an account:
Context
A couple of points to keep in mind for this sub-project:
Session DB level ID vs Code/User level Alias:
- Similarly to
accounts
which now has a DB level ID along with a code level 8 byte alias which is calledAccountID
in the code base, for sessions, we have asession.ID
(4 bytes) in the code base but we will now have a DB level int ID for sessions too. And just like for accounts, we want to continue being able to reference sessions using the alias for backwards compatibility.
- Note: I'll probably open PRs to rename these variables to beaccounts.Alias
andsessions.Alias
to remove confusion.
The link from a session to an account:
- Today, an account can be tied to a session but this is done implicitly by embedding the account ID in the session's macaroon caveat. In SQL land, however, we would want this link to be explicit via a foreign key. We'll then want to have tests that cover that we cant add a session linked to an account if that account doesnt exist yet - but to do this, we first need to make sure that the existing KVDB code also does not allow this. So there will be some prep work to add these checks for the existing logic before adding SQL stuff.
Session Creation flow
-
Today, a session is created as follows:
1) Lock Lit'ssessRegMu
mutex to ensure only one thread is trying to create a session at a time
2) call the session store'sdb.GetUnusedIDAndKeyPair
method to find an unused alias & private key pair.
3) call theNewSession
function to construct a newSessions
object (note: this does not touch the DB yet) .
4) Finally, call the store'sdb.CreateSession
method to actually go persist the new store.
5) unlocksessRegMu
.
6) (For linked sessions: we also use theCheckSessionGroupPredicate
to ensure any linked sessions are inactive.) -
How the above flow came about: For Autopilot sessions, we wanted to make sure we could successfully register a session with
Autopilot
before actually going and persisting it to our DB. But at the time of registration, we already want to know the ID/Local pub key pair we will use for the session. This is why we would do all this in-memory only work before actually persisting the session. This is also why we needed to lock the mutex to ensure only one thread callsdb.GetUnusedIDAndKeyPair
at a time. -
For a clean interface though, all the above should really happen atomically under a single database read transaction & we should not need to expose things like
db.GetUnusedIDAndKeyPair
anddb.CheckSessionGroupPredicate
. -
What we will instead do is:
- Add a newsession.State
:SessionReserved
, which will be the new first state of a session.
- Then, we will changeNewSession
to instead be a method on theStore
interface. This will
- take care of finding a unique ID/Local key pair (so we can remove that from the interface).
- insert the new session but under theReserved
state.
- if a group is linked, here is where we will check that all other sessions are revoked. SoCheckSessionGroupPredicate
can also be removed from the interface.
-CreateSession
will then only move a session fromReserved
toCreated
.
- On DB startup, we make sure to delete all sessions in theReserved
state.
Planed Moulding/Massaging Work:
- Rename
accounts.AccountID
toaccounts.Alias
- Add checks to existing code to ensure that an account exists before creating a session linked to it. With this, we will also include an
AccountID fn.Option[accounts.Alias]
member in theSession
struct. - Add a new
Reserved
session state & ensure to delete allReserved
sessions on startup (ie, all sessions that did not make it to theCreated
state. - Move the
CheckSessionGroupPredicate
functionality to insideCreateSession
- Move
NewSession
to be a method on theStore
interface, move logic fromCreateSession
to there and then letCreateSession
only change the state of a session toCreated