"Rights Amplification" term alternate?

Yep, you’ve implemented a rights amplification system even, see the group-style editing stuff :slight_smile:

1 Like

I would call that augmentation and not amplification. The idea is that you are augmenting as an newly constructed composite object the textfile.

See, I feel like ‘Rights composition’ feels a bit better? Amplification is probably closest technically and historically, but the associations make it a slippery concept. Rights composition meaning ‘Creating new rights out of different rights’

1 Like

I like “rights composition” better than any of the other proposals, even mine.

1 Like

There’s an aspect to rights amplification about unlocking that’s more than just composition though in that you can’t use the pure lambda calculus really to do it… it involves eq or sealers/unsealers either made out of eq or some kinda language-protected type system

Still, I like it better than rights amplification :slight_smile:

(But also MarkM mentioned that part of his challenge with it is that it wasn’t “rights” oriented in the way “erights” is above so maybe the word “rights” should be swapped out too.)

I still like “privilege unlocking” as above. :stuck_out_tongue_winking_eye:

You can do sealer&unsealers without using eq primitive. It does require lexical scoping and mutable cells.

It works via each sealer unsealer pair share a mutable cell via lexical scoping with the boxes made by the sealer and unsealed by the unsealer.

I thought all the sealers/unsealers attempts that didn’t either use language level protection (eg dynamically constructed language-constructed types) or eq? (aka what I call the “coat check pattern”, which is the most popularly thrown around version) was interceptable? I remember trying to implement any of these and you could MITM the answer or access to the sealer/unsealer itself.

Here is an example sealer unsealer in js:

const makeSealerAndUnseler = (brandmark) => {
  let cell = undefined;
  const sealer = (specimen) => {
    const box = () => {
      cell = specimen;
      return undefined;
    };
    return box;
  };
  const unsealer = (box) => {
    try {
      cell = undefined;
      box();
      const specimen = cell;
      return specimen;
    } catch (err) {
      throw new Error(“unsuccessfull unsealing”);
    }
  };
  return [sealer, unsealer];
}

as you can see, the only interception possible is of control flow when a box is called.
Such interception can be used for entering an infinit loop but that is just the same risk as calling any code untrusted by the caller. The other use is for to know when a particular box that has been proxied by an wrapping closure is being unsealed but not much beyond that.

Edited to fix a vulernability arising from me misrecalling on how this done.

1 Like

Thanks again @zarutian! This is a very interesting approach. And glad to see the vulnerability is fixed.

;; This is just constructed to be a unique value, eq? to nothing,
;; which can be compared by a user to see if the unsealing failed.
;; The sealer and unsealer do not themselves use it.
(define the-nothing (cons '*the* '*nothing*))

(define (make-sealer-and-unsealer)
  (define cell the-nothing)    ; Shared, temp private register
  (define (sealer specimen)    ; Sealer procedure
    (define (box run-me)       ; New sealed box procedure
      (set! cell specimen))    ; Set to temp register
    box)                       ; Return procedure
  (define (unsealer box)       ; Unsealer procedure
    (set! cell the-nothing)    ; Clear the register
    (box)                      ; Move sealed val to register
    cell)                      ; Return value from register
  (values sealer unsealer))    ; Return sealer, unsealer

Here’s a Scheme version of the same idea, heavily commented. Pretty neat!

1 Like

Kevin Reid made some interesting observations about sealers and unsealers. No matter which approach you take, it’s kind of disturbing from a functional programming approach, because normally a set of procedures run with the same number of arguments won’t matter, you’ll always be able to mix them interchangably. No matter what, sealers/unsealers introduce a strange identity-like, communication-channel-like (as in terms of both ends have part of a “dialogue” and shared context) disturbing aspect that we don’t see in say, the pure lambda calculus.

Note that every version of sealers and unsealers I’m aware of so far requires near, or at least same-machine, references in some way or another.

  • The “coat check pattern” uses identity of the “ticket”, so shortening must be done
  • The runtime-protected language type requires a type controlled by… well, one runtime
  • The temporary register approach above requires synchronous operations (in Goblins, this would use the $ operator; <- could not be used)

The first two, at least, could use asynchronous message passing. The final one absolutely requires synchronous behavior to work.

There is a version of sealers unsealers that uses public key cryptography.
Per such there is two public key pairs, one is used for encryption and one is used for signing.
How they are usually implemented is that they act like regular single vat sealers and unsealers until a sealed box is to be serialized via safe serialization. That box’es contents gets serialized into a bytestring, that then gets encrypted with the public encryption key, and finally that ciphertext gets signed with the private signing key.
When such a sealer is to be serialized, it has the public encryption key and the private signing key as part of its portrayal.
Conversely the unsealer has the private decryption key and the public signature verification key as part of its portrayal.
I can dig out or recreate an implementation of this upon request.

Note though this kind of sealer unsealer eather requires that only Selfless and Transparent objects to given to the sealer, or have access to the vats SwissNum or equiv mechanism (the stuff that makes sturdyrefs for objects on this vat) for handling Selfish and/or opaque objects.

It is more that just composition.

If holding x gives me authority X and holding y gives me authority Y, and someone composes x and y into z and given me z, then in many common useful patterns of composition, the authority I have by holding z is <= union(X, Y). Indeed, the point of many composition patterns is to attenuate authority, so the authority I have by holding z is < union(X, Y) in an intended way.

By amplification, I mean to highlight that special category of composition when holding z gives some authority not included in union(X, Y). There are many reasons to highlight this special category. Among them is that inadvertent confused deputy hazards in ocap systems arise only from amplification, and so we need to be vigilant to this extra hazard only when engaged in amplification.

See the circuit diagrams I refer to in "Rights Amplification" term alternate? - #11 by markm to understand why I find “amplification” so appealing for this distinction.

Since the thing being amplified are, in my general terminology, neither permissions nor erights, since they are authority, and since “privilege” is a notoriously vague term, I accept that my historical “rights amplification” was worse that “authority amplification”. And who doesn’t like a bit of alliteration anyway?

Further, in popular use “privilege” is used in such phrases as “Driving is a privilege, not a right.” What people mean by that is it can be taken away from you. I want to stay as far away as I can from any such implication. That was one of many reasons the ocap community switched from Needham and Schroder’s “Principle of Least Privilege” to “Principle of Least Authority” (POLA).

See, I think, Capability Myths Demolished for how amplification can reintroduce confused deputy hazards into ocap systems.

2 Likes

Actually, we should take the opportunity to make a further distinction. The kind of amplification shown at "Rights Amplification" term alternate? - #28 by zarutian should be called “authority amplification” because it is based on the behavior of the invoked objects. The kind of amplification done by WeakMaps, that use identity rather than behavior, is “permissions amplification”.

1 Like

Here is an yet to be run implementation of cryptographic sealer unsealer implementation. Probably made an error somewhere.

Another reason for the switch is that “POLA” rolls off the tongue, but saying “POLP” makes it sound like you just swallowed your gum. :grinning:

Coming back to the original (#1) reason for this thread is the confusion the word “amplification” causes among newcomers to capabilities. They seem to have a mental model of something that gives a single capability more authority. The word “composition” at least connotes that you’re talking about more than one. Also, “Composition”, in the sense of needing both the car key and the garage key to put the car in the garage, is one of Marc Stiegler’s 6 Aspects of Sharing.

That being said, the fact that the total authority is more than the union of the individual authorities calls for being more precise. Is there a term from mathematics we could use that has no connotation to the audiences that are confused in this way?

That being said, the fact that the total authority is more than the union of the individual authorities calls for being more precise

Synergy?

A good word with no misleading connotations, but I’m not sure I’d use it for a general audience. I’d prefer something that has the connotations I want to plant in their heads. “Composition” does that even though it misses the finer point. (Sometimes you have to sacrifice precision to achieve clarity in your audience.) Of course, “rights amplification” is perfectly fine for the right audience.

Composite Capabilities?