867 lines
38 KiB
Markdown
867 lines
38 KiB
Markdown
# Glossary
|
||
|
||
## Action
|
||
[Actions]: #action
|
||
[Action]: #action
|
||
|
||
In the [Syndicated Actor Model][], an *action* may be performed by an [actor][] during a
|
||
[turn][]. Actions are quasi-transactional, taking effect only if their containing turn is
|
||
committed.
|
||
|
||
Four core varieties of action, each with a matching variety of [event][], are offered across
|
||
all realisations of the [SAM][]:
|
||
|
||
- An *assertion* action publishes an [assertion][] at a [target entity][]. A unique [handle][]
|
||
names the assertion action so that it may later be retracted. For more detail, [see below on
|
||
Assertions][assertion].
|
||
|
||
- A *retraction* action withdraws a previously-published assertion from the target entity.
|
||
|
||
- A *message* action sends a [message][] to a target entity.
|
||
|
||
- A *synchronization* action carries a local [entity reference][] to a target entity. When it
|
||
eventually reaches the target, the target will (by default) immediately reply with a simple
|
||
acknowledgement to the entity reference carried in the request. For more detail, [see below
|
||
on Synchronization][Synchronization].
|
||
|
||
Beside the core four actions, many individual implementations offer action variants such as the
|
||
following:
|
||
|
||
- A *spawn* action will, when the containing turn commits, create a new actor running
|
||
alongside the acting party. In many implementations, spawned actors may optionally be
|
||
[linked][link] to the spawning actor.
|
||
|
||
- *Replacement* of a previously-established assertion, "altering" the target entity reference
|
||
and/or [payload][]. This proceeds, conventionally, by establishment of the new assertion
|
||
followed immediately by retraction of the old.
|
||
|
||
Finally, implementations may offer pseudo-actions whose effects are local to the acting party:
|
||
|
||
- Creation of a new [facet][].
|
||
|
||
- Creation of a new [entity reference][] associated with the [active facet][] denoting a
|
||
freshly-created local [entity][].
|
||
|
||
- Shutdown (stopping) of the [active facet][] or any other [facet][] within the acting party.
|
||
|
||
- Stopping of the current actor, either gracefully or with a simulated crash.
|
||
|
||
- Creation of a new [field/cell/dataflow variable][dataflow variable].
|
||
|
||
- Creation of a new [dataflow block][dataflow block].
|
||
|
||
- Creation of a new [linked task][] associated with the [active facet][].
|
||
|
||
- Scheduling of a new one-off or periodic [alarm][].
|
||
|
||
## Active Facet
|
||
[Active Facet]: #active-facet
|
||
|
||
The [facet][] associated with the [event][] currently being processed in an active [turn][].
|
||
|
||
## Actor
|
||
[Actors]: #actor
|
||
[Actor]: #actor
|
||
|
||
In the [Syndicated Actor Model][], an *actor* is an isolated thread of execution. An actor
|
||
repeatedly takes [events][] from its [mailbox][], handling each in a [turn][]. In many
|
||
implementations of the [SAM][], each actor is internally structured as a tree of [facets][].
|
||
|
||
## Alarm
|
||
[Alarm]: #alarm
|
||
See [timeout][].
|
||
|
||
## Assertion
|
||
[Assertion]: #assertion
|
||
[Assertions]: #assertion
|
||
|
||
- *verb.* To *assert* (or to *publish*) a value is to choose a [target entity][] and perform
|
||
an [action][] conveying an *assertion* to that entity.
|
||
|
||
- *noun.* An *assertion* is a [value][] carried as the payload of an assertion [action][],
|
||
denoting a relevant portion of a public aspect of the conversational state of the sending
|
||
party that it has chosen to convey to the recipient entity.
|
||
|
||
The [value][] carried in an assertion may, in some implementations, depend on one or more
|
||
[dataflow variables][]; in those implementations, when the contents of such a variable
|
||
changes, the assertion is automatically withdrawn, recomputed, and re-published (with a
|
||
fresh [handle][]).
|
||
|
||
## Attenuation
|
||
[Attenuation]: #attenuation
|
||
[Attenuated]: #attenuation
|
||
|
||
To *attenuate* a [capability][] (yielding an *attenuated capability*), a sequence of filters is
|
||
prepended to the possibly-empty list of filters attached to an existing capability. Each filter
|
||
either discards, rewrites, or accepts unchanged any [payload][] directed at the underlying
|
||
capability. A special pattern language exists in the [Syndicate network protocol][] for
|
||
describing filters; many implementations also allow in-memory capabilities to be filtered by
|
||
the same language.
|
||
|
||
## Capability
|
||
[Capability]: #capability
|
||
[Cap]: #capability
|
||
|
||
(a.k.a. **Cap**) Used roughly interchangeably with "[reference][]", connoting a security-,
|
||
access-control-, or privacy-relevant aspect.
|
||
|
||
## Cell
|
||
[Cell]: #cell
|
||
See [dataflow variable][].
|
||
|
||
## Compositional
|
||
[Compositional]: #compositional
|
||
|
||
To quote the [Stanford Encyclopedia of
|
||
Philosophy](https://plato.stanford.edu/entries/compositionality/#Clar), the "principle of
|
||
compositionality" can be understood to be that
|
||
|
||
> The meaning of a complex expression is determined by its structure and the meanings of its
|
||
> constituents.
|
||
|
||
People often implicitly intend "... *and nothing else*." For example, when I claim that the
|
||
[object-capability model][] is a compositional approach to system security, I mean that the
|
||
access conveyed by an assemblage of capabilties can be understood in terms of the access
|
||
conveyed by each individual capability taken in isolation, *and nothing else*.
|
||
|
||
## Configuration Scripting Language
|
||
|
||
**Main article: [The Configuration Scripting Language](./operation/scripting.md)**
|
||
|
||
The `syndicate-server` program includes a scripting language, used for configuration of the
|
||
server and its clients, population of initial dataspaces for the system that the
|
||
`syndicate-server` instance is part of, and scripting of simple behaviours in reaction to
|
||
appearance of assertions or transmission of messages.
|
||
|
||
The scripting language is [documented here](./operation/scripting.md).
|
||
|
||
## Conversational State
|
||
[Conversational State]: #conversational-state
|
||
[Conversational Frame]: #conversational-state
|
||
|
||
The collection of facts and knowledge held by a component participating in an ongoing
|
||
conversation about some task that the component is undertaking:
|
||
|
||
> The conversational state that accumulates as part of a collaboration among components can be
|
||
> thought of as a collection of facts. First, there are those facts that define the *frame* of
|
||
> a conversation. These are exactly the facts that identify the task at hand; we label them
|
||
> “framing knowledge”, and taken together, they are the “conversational frame” for the
|
||
> conversation whose purpose is completion of a particular shared task. Just as tasks can be
|
||
> broken down into more finely-focused subtasks, so can conversations be broken down into
|
||
> sub-conversations. In these cases, part of the conversational state of an overarching
|
||
> interaction will describe a frame for each sub-conversation, within which corresponding
|
||
> sub-conversational state exists. The knowledge framing a conversation acts as a bridge
|
||
> between it and its wider context, defining its “purpose” in the sense of the [Gricean
|
||
> Cooperative Principle]. [The following figure] schematically depicts these relationships.
|
||
>
|
||
> <span id="fig:conversation">![Figure 2 from Garnock-Jones 2017](./figures/conversation.svg)</span>
|
||
>
|
||
> Some facts define conversational frames, but *every* shared fact is contextualized *within*
|
||
> some conversational frame. Within a frame, then, some facts will pertain directly to the task
|
||
> at hand. These, we label “domain knowledge”. Generally, such facts describe global aspects of
|
||
> the common problem that remain valid as we shift our perspective from participant to
|
||
> participant. Other facts describe the knowledge or beliefs of particular components. These,
|
||
> we label “epistemic knowledge”.
|
||
>
|
||
> — <cite>Excerpt from [Chapter 2 of (Garnock-Jones
|
||
> 2017)](https://syndicate-lang.org/tonyg-dissertation/html/#x_2_2_0_0_1).</cite> The quoted
|
||
> section continues [here](https://syndicate-lang.org/tonyg-dissertation/html/#x_2_2_0_0_7).
|
||
|
||
In the [Syndicated Actor Model][], there is often a one-to-one correspondence between a
|
||
[facet][] and a conversational frame, with [fate-sharing][] employed to connect the lifetime of
|
||
the one with the lifetime of the other.
|
||
|
||
|
||
## Dataflow
|
||
[Dataflow]: #dataflow
|
||
|
||
A programming model in which changes in stored state automatically cause re-evaluation of
|
||
computations depending on that state. The results of such re-evaluations are themselves often
|
||
used to update a store, potentially triggering further re-computation.
|
||
|
||
In the [Syndicated Actor Model][], dataflow appears in two guises: first, at a coarse
|
||
granularity, among actors and entities in the form of changes in published [assertions][]; and
|
||
second, at fine granularity, many implementations include [dataflow variables][] and [dataflow
|
||
blocks][] for *intra*-actor dataflow-based management of [conversational state][] and related
|
||
computation.
|
||
|
||
## Dataflow Block
|
||
[Dataflow block]: #dataflow-block
|
||
[Dataflow blocks]: #dataflow-block
|
||
|
||
Implementations of the [Syndicated Actor Model][] often include some language feature or
|
||
library operation for marking a portion of code as participating in [dataflow][], where changes
|
||
in observed [dataflow variables][] cause re-evaluation of the code block.
|
||
|
||
For example, in [a Smalltalk implementation of the
|
||
SAM](https://syndicate-lang.org/code/#squeak),
|
||
|
||
```smalltalk
|
||
a := Turn active cell: 1.
|
||
b := Turn active cell: 2.
|
||
sum := Turn active cell: 0.
|
||
Turn active dataflow: [sum value: a value + b value].
|
||
```
|
||
|
||
Later, as `a` and `b` have their values updated, `sum` will automatically be updated by
|
||
re-evaluation of the block given to the `dataflow:` method.
|
||
|
||
Analogous code can be written in TypeScript:
|
||
|
||
```typescript
|
||
field a: number = 1;
|
||
field b: number = 2;
|
||
field sum: number = 0;
|
||
dataflow {
|
||
sum.value = a.value + b.value;
|
||
}
|
||
```
|
||
|
||
in Racket:
|
||
|
||
```racket
|
||
(define-field a 1)
|
||
(define-field b 2)
|
||
(define/dataflow sum (+ (a) (b)))
|
||
```
|
||
|
||
in Python:
|
||
|
||
```python
|
||
a = turn.field(1)
|
||
b = turn.field(2)
|
||
sum = turn.field(0)
|
||
@turn.dataflow
|
||
def maintain_sum():
|
||
sum.value = a.value + b.value
|
||
```
|
||
|
||
and in Rust:
|
||
|
||
```rust,noplayground
|
||
turn.dataflow(|turn| {
|
||
let a_value = turn.get(&a);
|
||
let b_value = turn.get(&b);
|
||
turn.set(&sum, a_value + b_value);
|
||
})
|
||
```
|
||
|
||
## Dataflow Variable
|
||
[Dataflow Variable]: #dataflow-variable
|
||
[Dataflow Variables]: #dataflow-variable
|
||
|
||
(a.k.a. **Field**, **Cell**) A *dataflow variable* is a store for a single value, used with
|
||
[dataflow blocks][] in [dataflow][] programming.
|
||
|
||
When the value of a dataflow variable is read, the active [dataflow block][] is marked as
|
||
*depending* on the variable; and when the value of the variable is updated, the variable is
|
||
marked as *damaged*, leading eventually to re-evaluation of dataflow blocks depending on that
|
||
variable.
|
||
|
||
## Dataspace
|
||
[Dataspaces]: #dataspace
|
||
[Dataspace]: #dataspace
|
||
|
||
In the [Syndicated Actor Model][], a *dataspace* is a particular class of [entity][] with
|
||
prescribed behaviour. Its role is to route and replicate published [assertions][] according to
|
||
the [declared interests][observe] of its peers.
|
||
|
||
See [here](./syndicated-actor-model.md#dataspaces) for a full explanation of dataspaces.
|
||
|
||
## Dataspace Pattern
|
||
[Dataspace Pattern]: #dataspace-pattern
|
||
|
||
In the [Syndicated Actor Model][], a *dataspace pattern* is a structured [value][] describing a
|
||
pattern over other values. The pattern language used in current Dataspace implementations and
|
||
in the Syndicate protocol is documented [here](protocols/syndicate/dataspacePatterns.md).
|
||
|
||
## E
|
||
[E language]: #e
|
||
[E]: #e
|
||
|
||
The E programming language is an [object-capability model][] Actor language that has strongly
|
||
influenced the [Syndicated Actor Model][].
|
||
|
||
Many good sources exist describing the language and its associated philosophy, including:
|
||
|
||
- [The ERights.org website](http://www.erights.org/), the home of E
|
||
|
||
- [E (programming language)](https://en.wikipedia.org/wiki/E_(programming_language)) on
|
||
Wikipedia
|
||
|
||
- Miller, Mark S. “Robust Composition: Towards a Unified Approach to Access Control and
|
||
Concurrency Control.” PhD, Johns Hopkins University, 2006.
|
||
[[PDF]](http://www.erights.org/talks/thesis/markm-thesis.pdf)
|
||
|
||
- Miller, Mark S., E. Dean Tribble, and Jonathan Shapiro. “Concurrency Among Strangers.” In
|
||
Proc. Int. Symp. on Trustworthy Global Computing, 195–229. Edinburgh, Scotland, 2005.
|
||
[[DOI]](https://dl.acm.org/doi/10.5555/1986262.1986274)
|
||
[[PDF]](http://www.erights.org/talks/promises/paper/tgc05.pdf)
|
||
|
||
## Embedded References
|
||
[Embedded References]: #embedded-references
|
||
|
||
In the [Syndicated Actor Model][], the [values][] carried by [assertions][] and [messages][]
|
||
may include [references][] to [entities][]. Because the SAM uses [Preserves][] as its data
|
||
language, the Preserves concept of an *embedded value* is used in the SAM to reliably mark
|
||
portions of a datum referring to SAM entities.
|
||
|
||
Concretely, in [Preserves text
|
||
syntax](https://preserves.dev/preserves-text.html), embedded values
|
||
appear prepended with `#:`. In messages transferred across links using the [Syndicate network
|
||
protocol][], references might appear as `#:[0 123]`, `#:[1 555]`, etc. etc.
|
||
|
||
## Entity
|
||
[Target Entity]: #entity
|
||
[Entities]: #entity
|
||
[Entity]: #entity
|
||
|
||
In the [Syndicated Actor Model][], an *entity* is a stateful programming-language construct,
|
||
located within an [actor][], that is the target of [events][]. Each entity has its own
|
||
behaviour, specifying in code how it responds to incoming events.
|
||
|
||
An entity is the SAM analogue of "object" in [E][]-style languages: an addressable construct
|
||
logically contained within and [fate-sharing][] with an [actor][]. The concept of "entity"
|
||
differs from "object" in that entities are able to respond to [assertions][], not just
|
||
[messages][].
|
||
|
||
In many implementations of the [SAM][], entities [fate-share][] with individual [facets][]
|
||
within their containing actor rather than with the actor as a whole: when the facet associated
|
||
with an entity is stopped, the entity becomes unresponsive.
|
||
|
||
## Erlang
|
||
[Erlang]: #erlang
|
||
|
||
[Erlang](https://www.erlang.org/) is a process-style Actor language that has strongly
|
||
influenced the [Syndicated Actor Model][]. In particular, Erlang's approach to
|
||
failure-handling, involving [supervisors][] arranged in [supervision trees][] and processes
|
||
(actors) connected via [links and monitors][links], has been influential on the SAM. In the
|
||
SAM, links and monitors become special cases of [assertions][], and Erlang's approach to
|
||
process [supervision][] is used directly and is an important aspect of SAM system organisation.
|
||
|
||
## Event
|
||
[Event]: #event
|
||
[Events]: #event
|
||
|
||
In the [Syndicated Actor Model][], an *event* is processed by an [entity][] during a [turn][],
|
||
and describes the outcome of an [action][] taken by some other [actor][].
|
||
|
||
Events come in four varieties corresponding to the four core [actions][] in the [SAM][]:
|
||
|
||
- An *assertion* event notifies the recipient entity of an [assertion][] published by some
|
||
peer. A unique [handle][] names the event so that later retraction of the assertion can be
|
||
correlated with the assertion event.
|
||
|
||
- A *retraction* event notifies the recipient entity of withdrawal of a previously-published
|
||
assertion.
|
||
|
||
- A *message* event notifies the recipient entity of a [message][] sent by some peer.
|
||
|
||
- A *synchronization* event, usually not handled explicitly by an entity, carries an [entity
|
||
reference][]. The recipient should arrange for an acknowledgement to be delivered to the
|
||
referenced entity once previously-received events that might modify the recipient's state
|
||
(or the state of a remote entity that it is proxy for) have been completely processed. For
|
||
more detail, [see below on Synchronization][Synchronization].
|
||
|
||
## Facet
|
||
[Facet]: #facet
|
||
[Facets]: #facet
|
||
|
||
In many implementations of the [Syndicated Actor Model][], a *facet* is a programming-language
|
||
construct representing a *conversation* and corresponding to a [conversational frame][]. Facets
|
||
are similar to the "nested threads" of Martin Sústrik's idea of [Structured
|
||
Concurrency](https://250bpm.com/blog:71/) (see also
|
||
[Wikipedia](https://en.wikipedia.org/wiki/Structured_concurrency)).
|
||
|
||
Every [actor][] is structured as a tree of facets. (Compare and contrast with [the diagram in
|
||
the entry for Conversational State](#fig:conversation).)
|
||
|
||
Every facet is either "running" or "stopped". Each facet is the logical owner of zero or more
|
||
[entities][] as well as of zero or more published [assertions][]. A facet's entities and
|
||
published assertions [share its fate][fate-sharing]. While a facet is running, its associated
|
||
entities are responsive to incoming events; when it stops, its entities become permanently
|
||
unresponsive. A stopped facet never starts running again. When a facet is stopped, all its
|
||
assertions are retracted and all its subfacets are also stopped.
|
||
|
||
Facets may have *stop handlers* associated with them: when a facet is stopped, its stop
|
||
handlers are executed, one at a time. The stop handlers of each facet are executed before the
|
||
stop handlers of its parent and before its assertions are withdrawn.
|
||
|
||
Facets may be explicitly stopped by a stop [action][], or implicitly stopped when an actor
|
||
crashes. When an actor crashes, its stop handlers are not run: stop handlers are for orderly
|
||
processing of conversation termination. Instead, many implementations allow actors to have
|
||
associated *crash handlers* which run only in case of an actor crash. In the limit, of course,
|
||
even crash handlers cannot be guaranteed to run, because the underlying hardware or operating
|
||
system may suffer some kind of catastrophic failure.
|
||
|
||
## Fate-sharing
|
||
[Fate-sharing]: #fate-sharing
|
||
[Fate-share]: #fate-sharing
|
||
|
||
A design principle from large-scale network engineering, due to David Clark:
|
||
|
||
> The fate-sharing model suggests that it is acceptable to lose the state information
|
||
> associated with an entity if, at the same time, the entity itself is lost.
|
||
>
|
||
> — <cite>David D. Clark, “The Design Philosophy of the DARPA Internet Protocols.” ACM SIGCOMM
|
||
> Computer Communication Review 18, no. 4 (August 1988): 106–14.
|
||
> [[DOI]](https://doi.org/10.1145/52325.52336)</cite>
|
||
|
||
In the [Syndicated Actor Model][], fate-sharing is used in connecting the lifetime of
|
||
[conversational state][] with the programming language representation of a conversational
|
||
frame, a [facet][].
|
||
|
||
## Field
|
||
[Field]: #field
|
||
See [dataflow variable][].
|
||
## Handle
|
||
[Handle]: #handle
|
||
|
||
In the [Syndicated Actor Model][], every [assertion][] [action][] (and the corresponding
|
||
[event][]) includes a [scope][]-lifetime-unique *handle* that denotes the specific action/event
|
||
concerned, for purposes of later correlation with a retraction action.
|
||
|
||
Handles are, in many cases, implemented as unsigned integers, allocated using a simple
|
||
scope-wide counter.
|
||
|
||
## Initial OID
|
||
[Initial OID]: #initial-oid
|
||
|
||
In the [Syndicate network protocol][], the initial OID is a special [OID][] value understood by
|
||
prior arrangement to denote an [entity][] (specified by the "[initial ref][]") owned by some
|
||
remote peer across some network medium. The initial OID of a session is used to bootstrap
|
||
activity within that session.
|
||
|
||
## Initial Ref
|
||
[Initial Ref]: #initial-ref
|
||
|
||
In the [Syndicate network protocol][], the initial ref is a special [entity reference][]
|
||
associated by prior arrangement with an [initial OID][] in a session in order to bootstrap
|
||
session activity.
|
||
|
||
## Linked Actor
|
||
[Links]: #linked-actor
|
||
[Link]: #linked-actor
|
||
[Linked Actor]: #linked-actor
|
||
[Linked Actors]: #linked-actor
|
||
|
||
Many implementations of the [Syndicated Actor Model][] offer a feature whereby an [actor][] can
|
||
be spawned so that its root [facet][] is *linked* to the spawning facet in the spawning actor,
|
||
so that when one terminates, so does the other (by default).
|
||
|
||
```ditaa
|
||
+-Actor 1---------------------------+
|
||
| +----------+ |
|
||
| |root facet| |
|
||
| | (1) | |
|
||
| ++--------++ |
|
||
| | | |
|
||
| +----++ ++----------+ |
|
||
| |sub– | |sub–facet | |
|
||
| |facet| |(1.3) | |
|
||
| |(1.2)| +-+--------++ |
|
||
| +-----+ | | | +-Actor 6------------+
|
||
| +-----+--+ ++-------+| presence| +----------+ |
|
||
| |sub–sub–| |sub–sub–+-------------->|root facet| |
|
||
| |facet | |facet |<--------------+ (6) | |
|
||
| |(1.3.4) | |(1.3.5) || presence ++--------++ |
|
||
| +--------+ +--------+| | | | |
|
||
| | |+----++ ++----+|
|
||
+-----------------------------------+ ||sub– | |sub– ||
|
||
||facet| |facet||
|
||
||(6.7)| |(6.8)||
|
||
|+-----+ +-----+|
|
||
+--------------------+
|
||
```
|
||
|
||
Links are implemented as a pair of "presence" [assertions][], atomically established at the
|
||
time of the [spawn action][action], each indicating to a special entity with "stop on
|
||
retraction" behaviour the presence of its peer. When one of these assertions is withdrawn, the
|
||
targetted entity stops its associated [facet][], automatically terminating any subfacets and
|
||
executing any stop handlers.
|
||
|
||
This allows a "parent" actor to react to termination of its child, perhaps releasing associated
|
||
resources, and the corresponding "child" actor to be automatically terminated when the facet in
|
||
its parent that spawned the actor terminates.
|
||
|
||
This idea is inspired by [Erlang][], whose
|
||
"[links](https://www.erlang.org/doc/reference_manual/processes.html#links)" are symmetric,
|
||
bidirectional, failure-propagating connections among Erlang processes (actors) and whose
|
||
"[monitors](https://www.erlang.org/doc/reference_manual/processes.html#monitors)" are
|
||
unidirectional connections similar to the individual "presence" assertions described above.
|
||
|
||
## Linked Task
|
||
[Linked Tasks]: #linked-task
|
||
[Linked Task]: #linked-task
|
||
|
||
Many implementations of the [Syndicated Actor Model][] offer the ability to associate a facet
|
||
with zero or more native threads, coroutines, objects, or other language-specific
|
||
representations of asynchronous activities. When such a facet stops (either by explicit [stop
|
||
action][action] or by crash-termination of the facet's actor), its linked tasks are also
|
||
terminated. By default, the converse is also the case: a terminating linked task will trigger
|
||
termination of its associated facet. This allows for resource management patterns similar to
|
||
those enabled by the related idea of [linked actors][].
|
||
|
||
## Macaroon
|
||
|
||
A *macaroon* is an access token for authorization of actions in distributed systems. Macaroons
|
||
were introduced in the paper:
|
||
|
||
[*“Macaroons: Cookies with Contextual Caveats for Decentralized Authorization in the
|
||
Cloud.”*](https://research.google/pubs/pub41892/), by Arnar Birgisson, Joe Gibbs Politz, Úlfar
|
||
Erlingsson, Ankur Taly, Michael Vrable, and Mark Lentczner. In Proc. Network and Distributed
|
||
System Security Symposium (NDSS), 2014. [[PDF]](https://research.google/pubs/pub41892.pdf)
|
||
|
||
In the [Syndicated Actor Model][], a variation of the macaroon concept is used to represent
|
||
"sturdyrefs". A [sturdyref](./operation/builtin/gatekeeper.md#sturdyrefs) is a long-lived token
|
||
authorizing interaction with some entity, which can be upgraded to a live [entity reference][]
|
||
by presenting it to a [gatekeeper entity](./operation/builtin/gatekeeper.md) across a session
|
||
of the [Syndicate network protocol][]. (The term "sturdyref" is lifted directly from the [E
|
||
language][] and associated ecosystem.)
|
||
|
||
## Mailbox
|
||
[Mailbox]: #mailbox
|
||
|
||
Every [actor][] notionally has a *mailbox* which receives [events][] resulting from its peers'
|
||
[actions][]. Each actor spends its existence waiting for an incoming event to appear in its
|
||
mailbox, removing the event, taking a [turn][] to process it, and repeating the cycle.
|
||
|
||
## Membrane
|
||
[Membrane]: #membrane
|
||
|
||
A *membrane* is a structure used in implementations of the [Syndicate network protocol][] to
|
||
keep track of [wire symbols][].
|
||
|
||
## Message
|
||
[Messages]: #message
|
||
[Message]: #message
|
||
|
||
In the [Syndicated Actor Model][], a *message* is a [value][] carried as the payload or *body*
|
||
of a message [action][] (and associated [event][]), conveying transient information from some
|
||
sending [actor][] to a recipient [entity][].
|
||
|
||
## Network
|
||
[Networks]: #network
|
||
[Network]: #network
|
||
|
||
A network is a group of peers ([actors][]), plus a medium of communication (a [transport][]),
|
||
an addressing model ([references][]), and an associated [scope][].
|
||
|
||
## Object-Capability Model
|
||
[Object-Capability Model]: #object-capability-model
|
||
|
||
The [Object-capability model](https://en.wikipedia.org/wiki/Object-capability_model) is a
|
||
compositional means of expressing access control in a distributed system. It has its roots in
|
||
operating systems research stretching back decades, but was pioneered in a programming language
|
||
setting by the [E language][] and the Scheme dialect
|
||
[W7](http://mumble.net/~jar/pubs/secureos/secureos.html).
|
||
|
||
In the [Syndicated Actor Model][], object-capabilities manifest as potentially-[attenuated][]
|
||
[entity references][].
|
||
|
||
## Observe
|
||
[Observe]: #observe
|
||
[Observation]: #observe
|
||
|
||
In the [Syndicated Actor Model][], [assertion][] of an `Observe` record at a [dataspace][]
|
||
declares an *interest* in receiving notifications about matching [assertions][] and
|
||
[messages][] as they are asserted, retracted and sent through the dataspace.
|
||
|
||
Each `Observe` record contains a [dataspace pattern][] describing a structural predicate over
|
||
assertion and message [payloads][], plus an [entity reference][] to the [entity][] which should
|
||
be informed as matching events appear at the dataspace.
|
||
|
||
## OID
|
||
[OID]: #oid
|
||
|
||
An *OID* is an "object identifier", a small, session-unique integer acting as an [entity
|
||
reference][] across a [transport][] link in an instance of the [Syndicate network protocol][].
|
||
|
||
## Publishing
|
||
|
||
To *publish* something is to *assert* it; see [assertion][].
|
||
|
||
## Preserves
|
||
[Preserves]: #preserves
|
||
|
||
**Main article: [Preserves](./guide/preserves.md)**
|
||
|
||
Many implementations of the [SAM][] use *Preserves*, a programming-language-independent
|
||
language for data, as the language defining the possible [values][] that may be exchanged among
|
||
[entities][] in [assertions][] and [values][].
|
||
|
||
See the [chapter on Preserves](./guide/preserves.md) in this manual for more information.
|
||
|
||
## Record
|
||
|
||
The [Preserves][] data language defines the notion of a *record*, a tuple containing a *label*
|
||
and zero or more numbered *fields*. The [dataspace pattern][] language used by [dataspaces][]
|
||
allows for patterns over records as well as over other compound data structures.
|
||
|
||
## Reference
|
||
[Entity References]: #reference
|
||
[Entity Reference]: #reference
|
||
[References]: #reference
|
||
[Reference]: #reference
|
||
[Ref]: #reference
|
||
[Refs]: #reference
|
||
|
||
(a.k.a. **Ref**, **Entity Reference**, **[Capability][]**) A *reference* is a pointer or handle
|
||
denoting a live, stateful [entity][] running within an [actor][]. The entity accepts
|
||
[Preserves][]-format [messages][] and/or [assertions][]. The capability may be [attenuated][]
|
||
to restrict the messages and assertions that may be delivered to the denoted entity by way of
|
||
this particular reference.
|
||
|
||
## Retraction
|
||
[Retraction]: #retraction
|
||
|
||
In the [Syndicated Actor Model][], a *retraction* is an [action][] (and corresponding
|
||
[event][]) which withdraws a previous [assertion][]. Retractions can be explicitly performed
|
||
within a [turn][], or implicitly performed during [facet][] shutdown or [actor][] termination
|
||
(both normal termination and crash stop).
|
||
|
||
The [SAM][] guarantees that an actor's assertions will be retracted when it terminates, no
|
||
matter whether an orderly shutdown or an exceptional or crashing situation was the cause.
|
||
|
||
## Relay
|
||
[Relays]: #relay
|
||
[Relay]: #relay
|
||
|
||
A *relay* connects [scopes][], allowing [references][] to denote [entities][] resident in
|
||
remote [networks][], making use of the [Syndicate network protocol][] to do so.
|
||
|
||
See the [Syndicate network protocol][] for more on relays.
|
||
|
||
## Relay Entity
|
||
[Relay Entity]: #relay-entity
|
||
|
||
A *relay entity* is a local proxy for an [entity][] at the other side of a [relay][] link. It
|
||
forwards [events][] delivered to it across its [transport][] to its counterpart at the other
|
||
end.
|
||
|
||
See the [Syndicate network protocol][] for more on relay entities.
|
||
|
||
## S6
|
||
|
||
[S6, "Skarnet's Small Supervision Suite"](https://skarnet.org/software/s6/), is
|
||
|
||
> a small suite of programs for UNIX, designed to allow process [supervision][] (a.k.a service
|
||
> supervision), in the line of daemontools and runit, as well as various operations on
|
||
> processes and daemons.
|
||
>
|
||
> — <cite>[The S6 website](https://skarnet.org/software/s6/)</cite>
|
||
|
||
Synit uses [`s6-log`](https://skarnet.org/software/s6/s6-log.html) to capture standard error
|
||
output from [the root system bus](./operation/system-bus.md#the-root-system-bus).
|
||
|
||
## Schema
|
||
[Schema]: #schema
|
||
|
||
A *schema* defines a mapping between [values][] and host-language types in various programming
|
||
languages. The mapping describes how to parse values into host-language data, as well as how to
|
||
unparse host-language data, generating equivalent values. Another way of thinking about a
|
||
schema is as a specification of the allowable shapes for data to be used in a particular
|
||
context.
|
||
|
||
Synit, and many programs making use of the [Syndicated Actor Model][], uses [Preserves][]'
|
||
[schema language](https://preserves.dev/preserves-schema.html) to define
|
||
schemas for many different applications.
|
||
|
||
For more, see [the section on schemas in the chapter on
|
||
Preserves](http://zip.kpn:3000/guide/preserves.html#schemas).
|
||
|
||
## Scope
|
||
[Scopes]: #scope
|
||
[Scope]: #scope
|
||
|
||
A *scope* maps [refs][] to the [entities][] they denote. Scopes exist in one-to-one
|
||
relationship to [networks][]. Because [message bodies][message] and [asserted
|
||
values][assertion] contain [embedded references][], each message and assertion transmitted via
|
||
some network is also inseparable from its scope.
|
||
|
||
Most [actors][] will participate in a single scope. However, [relay][] actors participate in
|
||
two or more scopes, translating refs back and forth as messages and assertions traverse the
|
||
relay.
|
||
|
||
**Examples.**
|
||
|
||
1. A process is a scope for in-memory values: in-memory refs contain direct pointers to
|
||
entities, which cannot be interpreted outside the context of the process's address space.
|
||
The "network" associated with the process's scope is the intra-process graph of object
|
||
references.
|
||
|
||
2. A TCP/IP socket (or serial link, or WebSocket, or Unix socket, etc.) is a scope for values
|
||
travelling between two connected processes: [refs on the wire][wire symbol] denote
|
||
entities owned by one or the other of the two participants. The "network" for a socket's
|
||
scope is exactly the two connected peers (NB. and is *not* the underlying TCP/IP network,
|
||
HTTP network, or Unix kernel that supports the point-to-point link).
|
||
|
||
3. An ethernet segment is a scope for values broadcast among stations: the embedded refs are
|
||
(MAC address, [OID][]) pairs. The network is the set of participating peers.
|
||
|
||
4. A running web page is a scope for the JavaScript objects it contains: both local and remote
|
||
entities are represented by JavaScript objects. The "network" is the JavaScript heap.
|
||
|
||
## Subscription
|
||
See [observation][].
|
||
## Supervision tree
|
||
[Supervision trees]: #supervision-tree
|
||
[Supervision tree]: #supervision-tree
|
||
|
||
A *supervision tree* is a concept borrowed from [Erlang][], where a root [supervisor][]
|
||
supervises other supervisors, which in turn supervise worker [actors][] engaged in some task.
|
||
As workers fail, their supervisors restart them; if the failures are too severe or too
|
||
frequent, their direct supervisors fail in turn, and the supervisors' supervisors take action
|
||
to recover from the failures.
|
||
|
||
## Supervisor
|
||
[Supervisors]: #supervisor
|
||
[Supervisor]: #supervisor
|
||
[Supervision]: #supervisor
|
||
|
||
A *supervisor* is an [actor][] or [facet][] whose role is to monitor the state of some service,
|
||
taking action to ensure its availability to other portions of a complete system. When the
|
||
service fails, the supervisor is able to restart it. If the failures are too severe or too
|
||
frequent, the supervisor can take an alternative action, perhaps pausing for some time before
|
||
retrying the service, or perhaps even terminating itself to give its own supervisor in a
|
||
[supervision tree][] a chance to get things back on track.
|
||
|
||
Synit uses supervisors extensively to monitor system daemons and other system services.
|
||
|
||
## Sync Peer Entity
|
||
|
||
The *sync peer entity* is the [entity reference][] carried in a [synchronization][] [action][]
|
||
or [event][].
|
||
|
||
## Synchronization
|
||
[Synchronization]: #synchronization
|
||
|
||
An [actor][] may *synchronize* with an [entity][] by scheduling a *synchronization* [action][]
|
||
targeted at that entity. The action will carry a local [entity reference][] acting as a
|
||
continuation. When the target entity eventually responds, it will transmit an acknowledgement
|
||
to the continuation entity reference carried in the request.
|
||
|
||
An entity receiving a synchronization [event][] should arrange for an acknowledgement to be
|
||
delivered to the referenced continuation entity once previously-received events that might
|
||
modify the recipient's state (or the state of a remote entity that it is proxy for) have been
|
||
completely processed.
|
||
|
||
Most entities do not explicitly include code for responding to synchronization requests. The
|
||
default code, which simply replies to the continuation immediately, usually suffices. However,
|
||
sometimes the default is not appropriate. For example, when [relay entity][] is proxying for
|
||
some remote entity via a [relay][] across a [transport][], it should react to synchronization
|
||
events by forwarding them to the remote entity. When the remote entity receives the forwarded
|
||
request, it will reply to its local proxy for the continuation entity, which will in turn
|
||
forward the reply back across the transport.
|
||
|
||
## Syndicate Protocol
|
||
[Syndicate Network Protocol]: #syndicate-protocol
|
||
[Syndicate Protocol]: #syndicate-protocol
|
||
[Protocol]: #syndicate-protocol
|
||
|
||
**Main article: [The Syndicate Protocol](./protocol.md)**
|
||
|
||
The Syndicate Protocol (a.k.a the **Syndicate Network Protocol**) allows [relays][] to proxy
|
||
entities from remote [scopes][] into the local scope.
|
||
|
||
For more, see [the protocol specification document](./protocol.md).
|
||
|
||
## Syndicated Actor Model
|
||
[Syndicated Actor Model]: #syndicated-actor-model
|
||
[SAM]: #syndicated-actor-model
|
||
|
||
**Main article: [The Syndicated Actor Model](./syndicated-actor-model.md)**
|
||
|
||
The *Syndicated Actor Model* (often abbreviated **SAM**) is the model of concurrency and
|
||
communication underpinning Synit. The SAM offers a “conversational” metaphor: programs meet and
|
||
converse in virtual locations, building common understanding of the state of their shared
|
||
tasks.
|
||
|
||
In the SAM, source [entities][] running within an [actor][] publish [assertions][] and send
|
||
[messages][] to target entities, possibly in other actors. The essential idea of the SAM is
|
||
that state replication is more useful than message-passing; message-passing protocols often end
|
||
up simulating state replication.
|
||
|
||
[A thorough introduction to the Syndicated Actor Model](./syndicated-actor-model.md) is
|
||
available.
|
||
|
||
## System Layer
|
||
|
||
The [*system layer*](system-layer.md) is an essential part of an operating system, mediating
|
||
between user-facing programs and the kernel. It provides the technical foundation for many
|
||
qualities relevant to system security, resilience, connectivity, maintainability and usability.
|
||
|
||
The concept of a system layer has only been recently recognised—the term itself was [coined by
|
||
Benno Rice in a 2019 conference
|
||
presentation](https://www.youtube.com/watch?v=o_AIw9bGogo)—although many of the ideas
|
||
it entails have a long history.
|
||
|
||
The hypothesis that the Synit system explores is that the [Syndicated Actor model][] provides a
|
||
suitable theoretical and practical foundation for a system layer. The system layer demands, and
|
||
the SAM supplies, well-integrated expression of features such as service naming, presence,
|
||
discovery and activation; security mechanism and policy; subsystem isolation; and robust
|
||
handling of partial failure.
|
||
|
||
## System Dataspace
|
||
|
||
The *system dataspace* in Synit is the primary dataspace entity, owned by an [actor][] running
|
||
within [the root system bus](./operation/system-bus.md#the-root-system-bus), and (selectively)
|
||
made available to daemons, system services, and user programs.
|
||
|
||
## Timeout
|
||
[Timeout]: #timeout
|
||
|
||
Many implementations of the [Syndicated Actor Model][] offer [actions][] for establishing
|
||
*timeouts*, i.e. one-off or repeating alarms. Timeouts are frequently implemented as [linked
|
||
tasks][].
|
||
|
||
## Transport
|
||
[Transport]: #transport
|
||
|
||
A *transport* is the underlying medium connecting one [relay][] to its counterpart(s) in an
|
||
instance of the [Syndicate network protocol][]. For example, a TLS-on-TCP/IP socket may connect
|
||
a pair of relays to one another, or a UDP multicast socket may connect an entire group of
|
||
relays across an ethernet.
|
||
|
||
## Turn
|
||
[Turn]: #turn
|
||
|
||
Each time an [event][] arrives at an [actor][]'s [mailbox][], the actor takes a *turn*. A turn
|
||
is the process of handling the triggering event, from the moment of its withdrawal from the
|
||
mailbox to the moment of the completion of its interpretation.
|
||
|
||
Relatedly, the programming-language *representation* of a turn is a convenient place to attach
|
||
the APIs necessary for working with the [Syndicated Actor Model][]. In many implementations,
|
||
some class named `Turn` or similar exposes methods corresponding to the [actions][] available
|
||
in the [SAM].
|
||
|
||
In the [SAM][], a turn comprises
|
||
|
||
- the [event][] that triggered the turn,
|
||
- the [entity][] addressed by the event,
|
||
- the [facet][] owning the targeted entity, and
|
||
- the collection of pending [actions][] produced during execution.
|
||
|
||
If a turn proceeds to completion without an exception or other crash, its pending actions are
|
||
*committed* (finalised and/or delivered to their target entities). If, on the other hand, the
|
||
turn is aborted for some reason, its pending actions are *rolled back* (discarded), the actor
|
||
is terminated, its assertions [retracted][retraction], and all its resources released.
|
||
|
||
## Value
|
||
[Values]: #value
|
||
[Value]: #value
|
||
[Payloads]: #value
|
||
[Payload]: #value
|
||
|
||
A [Preserves][] `Value` with embedded data. The embedded data are often [embedded references][]
|
||
but, in some implementations, may be other kinds of datum. Every [message][] body and every
|
||
[assertion][] payload is a value.
|
||
|
||
## Wire Symbol
|
||
[Wire Symbols]: #wire-symbol
|
||
[Wire Symbol]: #wire-symbol
|
||
|
||
A *wire symbol* is a structure used in implementations of the [Syndicate network protocol][] to
|
||
maintain a connection between an in-memory [entity reference][] and the equivalent name for the
|
||
entity as used in packets sent across the network.
|