Dynamic Sealing

This is an example of dynamic sealing in ocaps.

A sealer/unsealer pair is exposed through a brand. A sealer can produce a Box[Foo], and the box will prevent access to the boxed value. Unsealing the box with the unsealer will make it visible again.

Because a box can only be unsealed by objects that have the unsealer, this allows for passing values in the blind. Combined in the right manner, dynamic sealing can be used to implement responsibility tracking in capabilities.

Capability patterns often involve dynamic sealing in some form. Please see Capability Patterns for more information.

import ocaps._

// Brands allow for "flexible private fields" where
// you have lexical scoping or in situations where
// access modifiers are not suitable (i.e. there is not
// a containing class)
object DynamicSeal {

  trait Message

  case object Save extends Message

  case object Kill extends Message

  trait Decision

  case object Saved extends Decision

  case object Killed extends Decision

  // All of the users are of the same type, and so private fields
  // are no good here.  In addition, the boxed field is public
  // so anyone who is asking and who has the unsealer can see it.
  case class User(
    name: String,
    sentencer: User => User = identity,
    boxed: Option[Brand.Box[Message]] = None,
    private val brand: Option[Brand] = None
  ) {
    def sentence(user: User): User = sentencer(user)

    def process(user: User): Option[Message] = {
      for {
        box <- user.boxed
        brand <- brand
        message <- brand.unapply(box)
      } yield message

  def main(args: Array[String]): Unit = {
    val softBrand = Brand.create("Brand for Judge Softtouch")
    val doomBrand = Brand.create("Brand for Judge Doom")

    val judgeSofttouch = User("Judge Softtouch", sentencer = { user =>
      user.copy(boxed = Some(softBrand(Save)))
    }, brand = Some(softBrand))

    val judgeDoom = User("Judge Doom", sentencer = { user =>
      user.copy(boxed = Some(doomBrand(Kill)))
    }, brand = Some(doomBrand))

    val steve = judgeDoom.sentence(User("steve"))
    val will = judgeSofttouch.sentence(User("will"))
    val judgedDoom = judgeSofttouch.sentence(judgeDoom)

    val steveDecision = judgeDoom.process(steve)
      s"User ${steve.name} has message ${steve.boxed} and decision $steveDecision"
    val willDecision = judgeSofttouch.process(will)
      s"User ${will.name} has message ${will.boxed} and decision $willDecision"

    // What's going on here...
    val judgeDecision = judgedDoom.process(judgedDoom)
      s"User ${judgedDoom.name} has message ${judgedDoom.boxed} and decision $judgeDecision"

Full source at GitHub