Besides working on the new website, over the last couple of days I’ve
been consolidating the theory and implementation of secure/securable syndicated actors.
I decided to implement a syndicated-actor chat service similar to the
one @dustyweb implemented for Spritely Goblins (see
blog post
and code), to help draw out
the requirements and implementation constraints.
The code is here:
It went well. Using Preserves Schemas to define a protocol, and then using
capability attenuation to enforce conformant
use of the shared dataspace led to a system that prevented
users from forging messages from other users,
and prevented nick collisions from happening.
Here’s the schema defining the protocol:
version 1 .
embeddedType Actor.Ref .
UserId = int .
Join = <joinedUser @uid UserId @handle ref>.
NickClaim = <claimNick @uid UserId @name string @k ref>.
UserInfo = <user @uid UserId @name string>.
Says = <says @who UserId @what string>.
NickConflict = <nickConflict>.
The system has two moving pieces (besides the dataspace server
itself): a single “moderator”, and zero or more “clients”.
A client asserts interest in a Join record. In response to their
interest, the moderator allocates a user ID for the new connection and
a new session handle, and asserts a Join record back to the client
giving them access to their session.
The session handle is just a reference to the dataspace, attenuated to
allow access only using the uid assigned to the connection:
1
2
3
4
5
| attenuate(ds, rfilter(
pRec($Observe, pLit($user), pEmbedded()),
pRec($Observe, pLit($says), pEmbedded()),
pRec($claimNick, pLit(uid), pString(), pEmbedded()),
pRec($says, pLit(uid), pString()))),
|
Using this reference and trying to assert anything or send any message
not matching one of those patterns results in the assertion or message
being silently dropped.