<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title>Terracrypt</title><id>https://www.terracrypt.net/feeds/tags/ocap.xml</id><subtitle>Tag: ocap</subtitle><updated>2026-03-01T20:46:16Z</updated><link href="https://www.terracrypt.net/feeds/tags/ocap.xml" rel="self" /><link href="https://www.terracrypt.net" /><entry><title>Horton persistence progress</title><id>https://www.terracrypt.net/posts/decadv-horton-persist-debugging.html</id><author><name>Jonathan Frederickson</name><email>jonathan@terracrypt.net</email></author><updated>2025-12-27T12:03:00Z</updated><link href="https://www.terracrypt.net/posts/decadv-horton-persist-debugging.html" rel="alternate" /><content type="html">&lt;p&gt;I've gotten some work done towards supporting persistence in guile-horton over the last week or so, but I've hit a bit of a roadblock. Writing this up in part to explain what I've been working on and in part to think through it some more.&lt;/p&gt;&lt;p&gt;To support persistence, I need to switch all the actors in the system over to use the &lt;code&gt;define-actor&lt;/code&gt; macro. The &lt;code&gt;admin&lt;/code&gt; actor was previously using &lt;code&gt;selfish-spawn&lt;/code&gt;, but &lt;code&gt;define-actor&lt;/code&gt; has a &lt;code&gt;#:self&lt;/code&gt; parameter that should serve the same purpose. And the old code was using an internal cell for the mutable name functionality, which needs to be changed.&lt;/p&gt;&lt;p&gt;However... running into one particular problem that I'm still having trouble figuring out. When I spawn an &lt;code&gt;admin&lt;/code&gt;, that new object also spawns a &lt;code&gt;profile&lt;/code&gt; with a reference to that &lt;code&gt;admin&lt;/code&gt;.  In order to support that, the &lt;code&gt;admin&lt;/code&gt; needs to have a reference to itself; as mentioned above, &lt;a href=&quot;https://codeberg.org/terracrypt/guile-horton/commit/434baa4f0f20d3b5edf81385149718b53afb77ed&quot;&gt;I think I should be able to use a parameter on define-actor for that&lt;/a&gt;. But for some reason, &lt;a href=&quot;https://codeberg.org/terracrypt/guile-horton/commit/bc815da726ef5b7a7d8969b54ebb33ade8513e78&quot;&gt;the self parameter gets set to #&amp;lt;unspecified&amp;gt; when I try that&lt;/a&gt;. It's not clear to me why this might be happening from the docs, so I think I might need to do some source spelunking to figure it out.&lt;/p&gt;&lt;p&gt;Once I work that out, it looks like I'll run into &lt;a href=&quot;https://codeberg.org/spritely/goblins/issues/256&quot;&gt;this issue&lt;/a&gt;. It sounds like I should be able to work around that with a second object constructor, though it might be a bit messy.&lt;/p&gt;&lt;p&gt;This is part of my December Adventure 2025 series, which I haven't been as consistent with as I had hoped but has nudged me to work on this some at least! My adventure log for this year is &lt;a href=&quot;/posts/tags/da2025.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</content></entry><entry><title>Adding persistence to gobs-of-machines</title><id>https://www.terracrypt.net/posts/gobs-of-persistence.html</id><author><name>Jonathan Frederickson</name><email>jonathan@terracrypt.net</email></author><updated>2025-02-14T13:16:00Z</updated><link href="https://www.terracrypt.net/posts/gobs-of-persistence.html" rel="alternate" /><content type="html">&lt;p&gt;A couple updates on the &lt;a href=&quot;/posts/gobs-of-machines.html&quot;&gt;gobs-of-machines&lt;/a&gt; work from a while back!&lt;/p&gt;&lt;p&gt;The smaller update of the two: I've renamed what I was calling &amp;quot;provisioners&amp;quot; to &amp;quot;providers&amp;quot;. This is a bit of an attempt to align my terminology with that of other tools like &lt;a href=&quot;https://developer.hashicorp.com/terraform/language/providers&quot;&gt;Terraform&lt;/a&gt;. Ultimately when deploying real instances I'll need something to install/configure the hob-server component on the new machine, and it might make sense for &lt;em&gt;that&lt;/em&gt; to be called a &amp;quot;provisioner&amp;quot;. So I'm calling the part that interacts with cloud providers a &amp;quot;provider&amp;quot;. So much of this terminology is overloaded in devops tooling, but so it goes. :)&lt;/p&gt;&lt;p&gt;But the bigger change: the program now supports persistence! In practice, this means that you can shut down and restart the program (primarily the &lt;code&gt;boss&lt;/code&gt;), and when it comes back online it will remember the other instances that it's created.&lt;/p&gt;&lt;p&gt;This took a bit of troubleshooting (the errors you get when you forget something currently aren't as clear as they could be) but ultimately I was pleasantly surprised at how few changes I had to do to add persistence support!&lt;/p&gt;&lt;p&gt;The &lt;a href=&quot;https://files.spritely.institute/docs/guile-goblins/latest/Persistence.html&quot;&gt;Goblins docs on persistence&lt;/a&gt; explain this in more detail than I can here, but the changes mostly boiled down to:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Defining persistence environments for each custom object (and their dependencies)&lt;/li&gt;&lt;li&gt;Using &lt;code&gt;define-actor&lt;/code&gt; instead of &lt;code&gt;define&lt;/code&gt; for each of my objects&lt;/li&gt;&lt;li&gt;Pulling some of the variable definitions within each object into the object's constructor as optional parameters&lt;/li&gt;&lt;li&gt;Spawning my objects in persistent vats&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Walking through these:&lt;/p&gt;&lt;h2&gt;Defining persistence environments&lt;/h2&gt;&lt;p&gt;Each module that defines new objects needs to define a &amp;quot;persistence environment&amp;quot;. For &lt;code&gt;hob.scm&lt;/code&gt;, that looks like this:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define hob-env
  (make-persistence-env
   `((((gobs-of-machines hob) ^hob-server-presence) ,^hob-server-presence)
     (((gobs-of-machines hob) ^hob-client-presence) ,^hob-client-presence))
   #:extends common-env))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This gives Goblins some information it needs to snapshot and rehydrate objects: the module that the object is found in, the name of that object's constructor within that module, and the &amp;quot;object rehydrator&amp;quot; - which seems to be a direct reference to the object's constructor.&lt;/p&gt;&lt;p&gt;We extend another persistence env, &lt;code&gt;common-env&lt;/code&gt;, because the hob-client uses a &lt;code&gt;ghash&lt;/code&gt; to store bindings. So we need to tell Goblins how to persist &lt;code&gt;ghash&lt;/code&gt;es too, and &lt;code&gt;(goblins actor-lib common)&lt;/code&gt; provides a persistence env for the objects defined there that we can inherit from.&lt;/p&gt;&lt;h2&gt;Using &lt;code&gt;define-actor&lt;/code&gt; and pulling more into object constructors&lt;/h2&gt;&lt;p&gt;Goblins provides a macro called &lt;code&gt;define-actor&lt;/code&gt; that handles a lot of the persistence machinery for us. Using it in practice for e.g. the &lt;code&gt;hob-client-presence&lt;/code&gt; meant changing from this:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define (^hob-client-presence bcom)
  (define bindings (spawn ^ghash))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;...to this:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-actor (^hob-client-presence bcom #:optional (bindings (spawn ^ghash)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Instead of using an inner definition, I'm defining the &lt;code&gt;bindings&lt;/code&gt; hash table as an optional parameter to the object constructor, with its default value set to a newly spawned &lt;code&gt;ghash&lt;/code&gt;. To quote the Goblins manual:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;In most cases, and usually when using ‘define-actor’, we need to think the behavior and state being determined by the constructor, not relying on internal state.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;When the program starts, Goblins will recreate each object by spawning a new object with the same parameters, so moving state like this into the constructor allows it to recreate the previous state of the object.&lt;/p&gt;&lt;h2&gt;Using persistent vats&lt;/h2&gt;&lt;p&gt;This was the hardest part to work out.&lt;/p&gt;&lt;p&gt;To make use of Goblins's persistence features, you need to spawn your objects inside special vats that are persisted. The storage mechanism is pluggable, but for the time being the only one that actually saves to disk is the &lt;code&gt;syrup-store&lt;/code&gt;, so for now I'm using that. Spawning a &lt;code&gt;syrup-store&lt;/code&gt; looks like this:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define dummy-vat-store (make-syrup-store &amp;quot;/tmp/gobs-dummy-state&amp;quot;))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If I only had one vat to deal with, this (along with the persistence environment stuff mentioned in an earlier section) would be all that I would need to spawn a persistent vat. However, I had previously designed the application such that the &lt;code&gt;dummy-machine&lt;/code&gt; and &lt;code&gt;hob-client&lt;/code&gt; objects lived in a separate vat, to roughly simulate the fact that in reality these would be running on the newly provisioned machine.&lt;/p&gt;&lt;p&gt;Goblins persists one vat at a time, so what do you do when you have objects in two different vats holding references to each other? Well, there is a mechanism for that too - you can make use of something called a &lt;code&gt;persistence-registry&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define persistence-vat (spawn-vat))
(define persistence-registry
  (with-vat persistence-vat
            (spawn ^persistence-registry)))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And then each time you spawn a new persistent vat, you pass a reference to the persistence registry into the &lt;code&gt;spawn-persistent-vat&lt;/code&gt; call:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-values (dummy-vat dummy-provider)
  (spawn-persistent-vat
   dummy-env
   (lambda ()
     (spawn ^dummy-provider))
   dummy-vat-store
   #:persistence-registry persistence-registry))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;One noteworthy thing about &lt;code&gt;spawn-persistent-vat&lt;/code&gt; is that when using it, you spawn the first object in the vat at the same time as the vat itself. This first object acts as the &amp;quot;root&amp;quot; of the persistence graph, and for other objects in this vat to be persisted, this first object needs to hold a reference to them. (This will be important later.)&lt;/p&gt;&lt;p&gt;Also, If you're paying close attention, you may notice that this isn't where the &lt;code&gt;dummy-provider&lt;/code&gt; was previously spawned, and there's a reason for that.&lt;/p&gt;&lt;p&gt;Previously, I was creating a new vat for each new machine, and this became a problem, because vats aren't in the list of data types that can appear in a persistence graph! (Even persistent vats, it seems - though I wonder if that could be supported at some point or if there are hurdles to implementing that.)&lt;/p&gt;&lt;p&gt;So I had to refactor a bit. Now, the &lt;code&gt;boss&lt;/code&gt; takes an extra &lt;code&gt;providers&lt;/code&gt; parameter, which is a &lt;code&gt;ghash&lt;/code&gt; whose keys are each the provider name and the values are references to a provider object:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-actor (^boss bcom #:key [providers (spawn ^ghash)] [machines (spawn ^ghash)])&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Essentially I'm sidestepping the above limitation by spawning the &lt;code&gt;dummy-provider&lt;/code&gt; in a new persistent vat first, and then passing it into the &lt;code&gt;boss&lt;/code&gt; as an argument (with the &lt;code&gt;dummy-provider&lt;/code&gt; modified to spawn each new &lt;code&gt;dummy-machine&lt;/code&gt; in the same vat rather than spawning a new one each time).&lt;/p&gt;&lt;p&gt;And then, having done that, we can spawn the persistent vat our &lt;code&gt;boss&lt;/code&gt; will live in:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define syrup-store (make-syrup-store &amp;quot;/tmp/gobs-state&amp;quot;))
(define-values (my-vat my-boss)
  (spawn-persistent-vat
   boss-env
   (lambda ()
     (let* ((ht (spawn ^ghash)))
       ($ ht 'set 'dummy dummy-provider)
       (spawn ^boss #:providers ht)))
   syrup-store
   #:persistence-registry persistence-registry))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, the thing that had me scratching my head for a while had to do with a little quirk of that vat independence I mentioned earlier, as well as with the requirement that the root retain a reference to objects in that vat that will be persisted. Previously, when creating a new machine, the &lt;code&gt;hob-server&lt;/code&gt; for the new machine would ultimately get a reference to the new &lt;code&gt;hob-client&lt;/code&gt;. But the provider wasn't keeping a reference to that newly created &lt;code&gt;hob-client&lt;/code&gt; anywhere, and so when rehydrating the object graph it didn't come back.&lt;/p&gt;&lt;p&gt;Fixing this just involved &lt;a href=&quot;https://git.sr.ht/~jfred/gobs-of-machines/commit/a21407d7f41ea1e774e0572076eb52344945e2b2&quot;&gt;making the &lt;code&gt;dummy-machine&lt;/code&gt; object persist its &lt;code&gt;hob-client&lt;/code&gt; and making the &lt;code&gt;dummy-provider&lt;/code&gt; persist each of the &lt;code&gt;dummy-machine&lt;/code&gt;s&lt;/a&gt;, but it took a little bit of puzzling to figure out.&lt;/p&gt;&lt;h2&gt;Persistence in action&lt;/h2&gt;&lt;p&gt;Phew! Having made those changes, persistence now works:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;scheme@(gobs-of-machines main)&amp;gt; (define-values (vat boss) (start-daemon))
scheme@(gobs-of-machines main)&amp;gt; ,enter-vat vat
Entering vat '2'.  Type ',q' to exit.  Type ',help goblins' for help.
goblins/2@(gobs-of-machines main) [1]&amp;gt; ($ boss 'create-machine &amp;quot;test&amp;quot;)
dummy-provider: In a real implementation, this would talk to a cloud provider
goblins/2@(gobs-of-machines main) [1]&amp;gt; dummy-machine: Creating new machine
dummy: Registered new client machine

goblins/2@(gobs-of-machines main) [1]&amp;gt; ($ boss 'list-machines)
$6 = (&amp;quot;test&amp;quot;)

&amp;lt;...then after killing and restarting the repl...&amp;gt;

scheme@(gobs-of-machines main)&amp;gt; (define-values (vat boss) (start-daemon))
scheme@(gobs-of-machines main)&amp;gt; ,enter-vat vat
Entering vat '2'.  Type ',q' to exit.  Type ',help goblins' for help.
goblins/2@(gobs-of-machines main) [1]&amp;gt; ($ boss 'list-machines)
$6 = (&amp;quot;test&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Success!&lt;/p&gt;&lt;p&gt;Obviously, there are still a couple tweaks that need to be made before this is really useful as a standalone application. There are some hardcoded &lt;code&gt;/tmp&lt;/code&gt; filenames lying around for the two persistent vats; the location for those needs to be configurable. It still needs a command-line entrypoint and a config file, so you can start and configure it from outside a REPL. And it still needs at least one real provider implementation! But it's a start. :)&lt;/p&gt;</content></entry><entry><title>Smalltalk and capabilities: a vision of a road not taken for desktop computing (and beyond?)</title><id>https://www.terracrypt.net/posts/smalltalk-ocap.html</id><author><name>Jonathan Frederickson</name><email>jonathan@terracrypt.net</email></author><updated>2024-10-27T23:13:00Z</updated><link href="https://www.terracrypt.net/posts/smalltalk-ocap.html" rel="alternate" /><content type="html">&lt;p&gt;&lt;em&gt;This is my submission for the Malleable Systems Collective's &lt;a href=&quot;https://forum.malleable.systems/t/challenge-problem-fearless-extensibility/205&quot;&gt;&amp;quot;Fearless extensibility&amp;quot; challenge problem&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;I've had a brainworm for the last few years that's been bugging me. Way back in &lt;a href=&quot;./free-software-is-not-enough-on-practical-user-freedom.html&quot;&gt;this blog post&lt;/a&gt;, I linked a video that demoed an early Smalltalk system. The most mind-blowing thing about that demo for me was that, on those early systems, you could make connections between and thus compose different graphical widgets.&lt;/p&gt;&lt;p&gt;I recommend watching the video to really see it in action, but it looked like this:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;../images/smalltalk-bouncing2.png&quot; alt=&quot;Screenshot of an early Smalltalk system showing off its abilty to make connections between widgets. There is a widget showing an animation of a bouncing ball, and an editor widget below it editing a specific frame of that animation.&quot; /&gt;&lt;/p&gt;&lt;p&gt;At this point in the demo, Alan Kay is using a picture editor widget to edit a specific frame of a bouncing ball animation. These aren't applications in the sense that we'd think of them today; they're separate pieces of software that are nonetheless working together.&lt;/p&gt;&lt;p&gt;This really underscored to me that the conventional UI wisdom I was familiar with (that command lines are composable and GUIs are not) wasn't the whole story. It would be more accurate to say that &lt;em&gt;today's&lt;/em&gt; GUIs are not composable, but GUIs in general certainly can be - it's just a different point in the design space!&lt;/p&gt;&lt;p&gt;Of course, this Smalltalk system was designed in the 70s for a very different computing landscape than the one we have today. Notably, at the time, you wouldn't have been running much software that wasn't written by either you or the computer vendor. The commercial software industry wasn't really a thing yet! Contrast that with the computers of today, where there's a very good chance that &lt;em&gt;most&lt;/em&gt; of the software you're running isn't from Microsoft, or Apple, or whoever made your computer. And similarly, computers back then weren't used for nearly as many sensitive tasks as they are today; you wouldn't have been doing online banking from your Alto. In today's world, you might not want just any software you download to be able to modify anything else on your system in such a deep way.&lt;/p&gt;&lt;p&gt;There's a philosophy aiming to address this that I've been interested in for the last few years called the object-capability security model. If you're unfamiliar with the concept, I recommend reading &lt;a href=&quot;http://habitatchronicles.com/2017/05/what-are-capabilities/&quot;&gt;What Are Capabilities&lt;/a&gt; by Chip Morningstar for a solid introduction. Something that comes up repeatedly in capability discussions is that ideally, capability transfer should happen via unambiguous user intent. The above blog post provides an example:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Imagine that when Word starts running it has no access at all to anything that’s access controlled – no files, peripheral devices, networks, nothing. When you double click the file icon or pick from the open file dialog, instead of giving Word a pathname string, the operating system itself opens the file and gives Word a handle to it (that is, it gives Word basically the same thing it would have given Word in response to the Open File API call when doing things the old way). Now Word has access to your document, but that’s all. It can’t send your file to Macedonia, because it doesn’t have access to the network – you didn’t give it that, you just gave it the document. It can’t delete or encrypt any of your other files, because it wasn’t given access to any of them either. It can mess up the one file you told it to edit, but it’s just the one file, and if it did that you’d stop using Word and not suffer any further damage. And notice that the user experience – your experience – is exactly the same as it was before. You didn’t have to answer any “mother may I?” security questions or put up with any of the other annoying stuff that people normally associate with security. In this world, that handle to the open file is an example of what we call a “capability”.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;It strikes me that the inter-object Alto demo could be done in a capability-secure way! During the demo, we see a painter object and an animation object, and Alan Kay &amp;quot;draws a line&amp;quot; between the two objects. He inspects each object's properties to see what's available on each, and in the box in between the two objects, he establishes a link between the painter's &lt;code&gt;picture&lt;/code&gt; and the animation's &lt;code&gt;currentFrame&lt;/code&gt;. This feels compatible with a capability system!&lt;/p&gt;&lt;p&gt;One way that I can think of that this might work: the interface outside of each object is part of a more trusted system UI, which has references to each object it manages. By default, each visible object in this system need not have references to any other object, but the system UI (having references to both) can pass references between them. When you draw a line between objects and pass the &lt;code&gt;currentFrame&lt;/code&gt; to the painter's &lt;code&gt;picture&lt;/code&gt; (which happens outside the context of any particular object), the system UI would send the painter a reference to a part of the animation object.&lt;/p&gt;&lt;p&gt;By building a system like this, we might gain a few things:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Objects could be instantiated from untrusted authors with minimal authority by default. Until the user connects the new object to another, it need not be able to communicate with other objects in the system.&lt;/li&gt;&lt;li&gt;We'd regain the ability to deeply compose graphical software, &lt;em&gt;even though&lt;/em&gt; the user may not fully trust the developer of the software they're using.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;But, a few open questions that I have:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Could you model things like network access as just more objects in the system while making the UX reasonably straightforward? Maybe drawing a line to a network icon lets you do this?&lt;/p&gt;&lt;ul&gt;&lt;li&gt;You may want the UI to be able to &amp;quot;minimize&amp;quot; connections between objects to avoid clutter.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Would some sort of structural editor in the &amp;quot;in-between&amp;quot; box be helpful for users? A blank text box is intimidating, but if the UI shows you what can go where with a menu (maybe &lt;a href=&quot;https://github.com/disconcision/fructure&quot;&gt;Fructure&lt;/a&gt;-style?) it might help ease people into this.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;There's a lot I don't know about how Smalltalk is implemented, and I'm sure there are a lot of details that would need to be worked out to implement something like this. But I think it's a path that could work, and it's something I'd like to see. :)&lt;/p&gt;</content></entry></feed>