Bring manual up to date and repair links

This commit is contained in:
Tony Garnock-Jones 2023-02-07 13:30:13 +01:00
parent fd8e32d655
commit 3d9b377a62
7 changed files with 116 additions and 77 deletions

View File

@ -307,7 +307,7 @@ language, the Preserves concept of an *embedded value* is used in the SAM to rel
portions of a datum referring to SAM entities.
Concretely, in [Preserves text
syntax](https://preserves.dev/preserves.html#textual-syntax), embedded values
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.

View File

@ -60,11 +60,11 @@ automatically, losslessly translatable from one syntax to another because Preser
are syntax-independent.
The core Preserves specification defines a text-based, human-readable, JSON-like syntax, that
is a syntactic superset of JSON, and a completely equivalent compact binary syntax, crucial to
the definition of [canonical form](#canonical-form) for Preserves values.[^syrup]
is a syntactic superset of JSON, and a completely equivalent compact machine-oriented syntax,
crucial to the definition of [canonical form](#canonical-form) for Preserves values.[^syrup]
Here are a few example values, written using the text syntax (see [the
specification](https://preserves.dev/preserves.html#textual-syntax) for the
specification](https://preserves.dev/preserves-text.html) for the
grammar):
Boolean : #t #f
@ -84,10 +84,10 @@ Commas are optional in sequences, sets, and dictionaries.
### Canonical form
Every Preserves value can be serialized into a *canonical form* using the [binary
syntax](https://preserves.dev/preserves.html#compact-binary-syntax) along with
[a few simple rules](https://preserves.dev/canonical-binary.html) about
serialization ordering of elements in sets and keys in dictionaries.
Every Preserves value can be serialized into a *canonical form* using the [machine-oriented
syntax](https://preserves.dev/preserves-binary.html) along with [a few simple
rules](https://preserves.dev/canonical-binary.html) about serialization ordering of elements in
sets and keys in dictionaries.
Having a canonical form means that, for example, a cryptographic hash of a value's canonical
serialization can be used as a unique fingerprint for the value.

View File

@ -39,15 +39,15 @@ The following definitions are taken from the
schema. For further detail, see the [reference](../../protocols/syndicate/gatekeeper.md).
```preserves-schema
SturdyRef = <ref @oid any @caveatChain [Attenuation ...] @sig bytes>.
SturdyRef = <ref @oid any @caveatChain [Caveat ...] @sig bytes>.
```
Within a `ref` record, the `oid` field is a free-form value that the targeted service chooses
to name itself. The `sig` is an iterated keyed-HMAC construction, just as in [macaroons][].
First, the service's secret key is used to key an HMAC of the `oid`. Then, the result is used
to key an HMAC of the first `Attenuation` in `caveatChain`. Each `Attenuation`'s HMAC becomes
the key for the next in the `caveatChain`. The final result is equal to the `sig` field in a
valid sturdyref.
to key an HMAC of the ([canonical form](../../guide/preserves.md#canonical-form) of the) first
`Caveat` in `caveatChain`. Each `Caveat`'s HMAC becomes the key for the next in the
`caveatChain`. The final result is equal to the `sig` field in a valid sturdyref.
### Attenuation of authority
@ -56,19 +56,13 @@ sturdyref, the `caveatChain` is used to [attenuate](../../glossary.md#attenuatio
authority denoted by the sturdyref by filtering and/or rewriting assertion and message bodies.
The `caveatChain` is run *right to left*, with newer rewrites-and-filters at the right-hand end
of the chain and older ones at the left-hand end. Of course, an empty `caveatChain` is an
unattenuated reference.
unattenuated reference. The structure and interpretation of `Caveat`s is described fully in
[the relevant section of the Syndicate network protocol
specification](../../protocol.md#attenuation-of-authority).
```preserves-schema
Attenuation = [Caveat ...].
```
Each individual `Attenuation` in a `caveatChain` is a sequence of `Caveat`s. The term "caveat"
is shamelessly taken from [macaroons][], though our caveats presently embody only what in the
Macaroons paper are called "first-party caveats" over assertion structure; future versions of
the server may add "third-party caveats" and other, richer, predicates over assertions.
Each `Attenuation`'s `Caveat`s are run in *right to left* order. The structure and
interpretation of `Caveat`s is described fully in [the relevant section of the Syndicate
network protocol specification](../../protocol.md#attenuation-of-authority).
The term "caveat" is shamelessly taken from [macaroons][], though our caveats presently embody
only what in the Macaroons paper are called "first-party caveats" over assertion structure;
future versions of the server may add "third-party caveats" and other, richer, predicates over
assertions.
[Macaroons]: ../../glossary.md#macaroon

View File

@ -31,13 +31,13 @@ name](#the-active-target).
*Program* = *Instruction* ...
A configuration source file is a file whose name ends in `.pr` that contains zero or more
Preserves [text-syntax](https://preserves.dev/preserves.html#textual-syntax)
Preserves [text-syntax](https://preserves.dev/preserves-text.html)
values, which are together interpreted as a sequence of *Instruction*s.
**Comments.** [Preserves
comments](https://preserves.dev/conventions.html#comments) are ignored. One
unfortunate wart is that because Preserves comments are really
[annotations](https://preserves.dev/preserves.html#annotations), they are
[annotations](https://preserves.dev/preserves-text.html#annotations), they are
required by the Preserves data model to be attached to some other value. Syntactically, this
manifests as the need for *some non-comment following every comment*. In scripts written to
date, often an empty *SequencingInstruction* serves to anchor comments at the end of a file:
@ -182,7 +182,7 @@ facet terminates, *Instruction* is run.
    `dataspace` |
    `timestamp` |
    `facet` |
`stringify` *ConvenienceExpr* |
    `stringify` *ConvenienceExpr* |
    *ValueExpr*
Values can be destructured and new variables introduced into the environment with `let`, which
@ -248,30 +248,47 @@ special syntax for *[attenuated](../glossary.md#attenuation) entity references*,
## Attenuation Expressions
*AttenuationExpr* = `<* $`*var*` [`*Rewrite* ...`]>`
*AttenuationExpr* = `<* $`*var*` [`*Caveat* ...`]>`
*Caveat* =
    `<or [`*Rewrite* ...`]>` |
    `<reject `*PatternExpr*`>` |
    *Rewrite*
*Rewrite* =
    `<filter `*PatternExpr*`>` |
    `<accept `*PatternExpr*`>` |
    `<rewrite `*PatternExpr*` `*TemplateExpr*`>`
An attenuation expression looks up *var* in the environment, asserts that it is an entity
reference *orig*, and returns a new entity reference *ref*, like *orig* but
[attenuated](../glossary.md#attenuation) with zero or more *Rewrite*s. The result of evaluation
[attenuated](../glossary.md#attenuation) with zero or more *Caveat*s. The result of evaluation
is *ref*, the new attenuated entity reference.
When an assertion is published or a message body arrives at *ref*, the sequence of *Rewrite*s
is executed left-to-right. If a *Rewrite* succeeds, the value if produces is forwarded on to
*orig*. If all *Rewrite*s fail, the assertion or message is silently ignored.
When an assertion is published or a message arrives at *ref*, the sequence of *Caveats*s is
executed **right-to-left**, transforming and possibly discarding the asserted value or message
body. If all *Caveat*s succeed, the final transformed value is forwarded on to *orig*. If any
*Caveat* fails, the assertion or message is silently ignored.
A `rewrite` *Rewrite* matches values with *PatternExpr*. If the match fails, the next *Rewrite*
is tried; if it succeeds, the resulting bindings are used along with the current environment to
evaluate *TemplateExpr*, and the resulting value is forwarded on to *orig*.
A *Caveat* can be one of three possibilities:
A `filter` *Rewrite* is the same as `<rewrite <?`*v*` `*PatternExpr*`> $`*v*`>`, for some fresh
*v*.
- An `or` of multiple alternative *Rewrite*s. The first *Rewrite* to accept (and possibly
transform) the input value causes the whole `or` *Caveat* to succeed. If all the *Rewrite*s
in the `or` fail, the `or` itself fails. Supplying a *Caveat* that is an `or` containing
zero *Rewrite*s will reject *all* assertions and messages.
Supplying zero *Rewrite*s will cause the new entity to reject *all* assertions and messages
sent to it.
- A `reject`, which allows all values through unchanged except those matching *PatternExpr*.
- A simple *Rewrite*.
A *Rewrite* can be one of two possibilities:
- A `rewrite`, which matches input values with *PatternExpr*. If the match fails, the
*Rewrite* fails. If it succeeds, the resulting bindings are used along with the current
environment to evaluate *TemplateExpr*, and the *Rewrite* succeeds, yielding the resulting
value.
- An `accept`, which is the same as `<rewrite <?`*v*` `*PatternExpr*`> $`*v*`>` for some fresh
*v*.
## Pattern Expressions
@ -348,10 +365,10 @@ binding the resulting capability to `$sys`. Any `require-service` record publish
rewritten into a `require-core-service` record; other assertions are forwarded unchanged.
```preserves
let ?sys = <* $config [
let ?sys = <* $config [<or [
<rewrite <require-service ?s> <require-core-service $s>>
<filter _>
]>
<accept _>
]>]>
```
Then, `$sys` is used to build the initial environment for a [configuration

View File

@ -124,10 +124,10 @@ expression](./scripting.md#attenuation-expressions) rewrites `require-service` a
`require-core-service` assertions:
```preserves
let ?sys = <* $config [
let ?sys = <* $config [<or [
<rewrite <require-service ?s> <require-core-service $s>>
<filter _>
]>
<accept _>
]>]>
<require-service <config-watcher "/etc/syndicate/core" {
config: $sys

View File

@ -172,7 +172,7 @@ additional conditions on the receiver's use of its own capability, known as an
An attenuation is a chain of `Caveat`s.[^caveat-terminology-macaroon] A `Caveat` acts as a
function that, given a Preserves value representing an assertion or message body, yields either
a possibly-rewritten value, or no value at all.[^zero-or-more] In the latter case, the value
a possibly-rewritten value, or no value at all.[^affine-caveats] In the latter case, the value
has been *rejected*. In the former case, the rewritten value is used as input to the next
`Caveat` in the chain, or as the final assertion or message body for delivery to the entity
backing the capability.
@ -183,17 +183,23 @@ leftward `Caveat` in the sequence. If no `Caveat`s are present, the capability i
and inputs are passed through to the backing capability unmodified.
```preserves-schema
Caveat = Rewrite / Alts .
Rewrite = <rewrite @pattern Pattern @template Template>.
Caveat = Rewrite / Alts / Reject / @unknown any .
Rewrite = <rewrite @pattern Pattern @template Template> .
Reject = <reject @pattern Pattern> .
Alts = <or @alternatives [Rewrite ...]>.
```
A `Caveat` can be either a single `Rewrite` or a sequence of alternative possible rewrites,
tried in left-to-right order until one of them accepts the input or there are none left to try.
(A single `Rewrite` *R* is equivalent to `<or [`*R*`]>`.)
A `Caveat` can be:
A `Rewrite` applies its `Pattern` to the input to the `Caveat`. If it matches, the bindings
- a single `Rewrite`[^single-rewrite-meaning], or a sequence of alternative possible rewrites
`Alts`, to be tried in left-to-right order until one of them accepts the input or there are
none left to try;
- a `Reject`, which passes all inputs unmodified except those matching the contained pattern; or
- an `unknown` caveat, which rejects all inputs.
Each `Rewrite` applies its `Pattern` to its input. If the `Pattern` matches, the bindings
captured by the pattern are gathered together and used in instantiation of the `Rewrite`'s
`Template`, yielding the output from the `Caveat`. If the pattern does not match, the `Rewrite`
has rejected the input, and other `alternatives` are tried until none remain, at which point
@ -518,6 +524,10 @@ The value is recursively traversed. As the relay comes across each embedded `Wir
- In each case, the `WireSymbol` associated with the OID has its reference count incremented
(if an `Assert` is being processed).
In addition, for `Assert` events, the `WireSymbol` (necessarily in the export membrane)
associated with the OID to which the incoming `Assert` is targetted has its reference count
incremented.
### <span id="outbound-rewriting"></span>Rewriting embedded references for transmission
When transmitting a `Value` *v* in an `Assert` or `Message` event, embedded references in *v*
@ -686,13 +696,13 @@ care should be taken in the case of non-cryptographic transport protocols like p
To use such a transport for this protocol, establish a connection and begin transmitting
[`Packet`s](#packet-definitions) encoded as Preserves values using either the Preserves [text
syntax](https://preserves.dev/preserves.html#textual-syntax) or the Preserves
[binary syntax](https://preserves.dev/preserves.html#compact-binary-syntax).
syntax](https://preserves.dev/preserves-text.html) or the Preserves
[machine-oriented syntax](https://preserves.dev/preserves-binary.html).
The session starts with the first packet and ends with transport disconnection. If either peer
in a connection detects a syntax error, it MUST disconnect the transport. A responding server
MUST support the binary syntax, and MAY also support the text syntax. It can autodetect the
syntax variant by following [the rules in the
specification](https://preserves.dev/preserves.html#appendix-autodetection-of-textual-or-binary-syntax):
specification](https://preserves.dev/preserves-binary.html#appendix-autodetection-of-textual-or-binary-syntax):
the first byte of a valid binary-syntax Preserves document is guaranteed not to be
interpretable as the start of a valid UTF-8 sequence.
@ -771,8 +781,9 @@ version 1 .
Attenuation = [Caveat ...].
Caveat = Rewrite / Alts .
Rewrite = <rewrite @pattern Pattern @template Template>.
Caveat = Rewrite / Alts / Reject / @unknown any .
Rewrite = <rewrite @pattern Pattern @template Template> .
Reject = <reject @pattern Pattern> .
Alts = <or @alternatives [Rewrite ...]>.
Oid = int .
@ -793,7 +804,7 @@ PCompound =
/ @dict <dict @entries { any: Pattern ...:... }> .
Template = TAttenuate / TRef / Lit / TCompound .
TAttenuate = <attenuate @template Template @attenuation Attenuation>.
TAttenuate = <attenuate @template Template @attenuation [Caveat ...]>.
TRef = <ref @binding int>.
TCompound =
/ @rec <rec @label any @fields [Template ...]>
@ -806,8 +817,8 @@ TCompound =
### Attenuation
```python
def attenuate(attenuation, value):
for caveat in reversed(attenuation):
def attenuate(caveats, value):
for caveat in reversed(caveats):
value = applyCaveat(caveat, value)
if value is None:
return None
@ -822,6 +833,13 @@ def applyCaveat(caveat, value):
return None
if caveat is 'Rewrite' variant:
return tryRewrite(caveat, value)
if caveat is 'Reject' variant:
if applyPattern(caveat.pattern, value) is None:
return value
else:
return None
if caveat is 'unknown' variant:
return None
def tryRewrite(rewrite, value):
bindings = applyPattern(rewrite.pattern, value)
@ -947,10 +965,6 @@ def instantiate(template, bindings):
mechanism. Future versions of this specification may opt to include some of this
generality.
[^zero-or-more]: TODO: It might be better to have a `Caveat` yield *zero or more* values? That
way they can act as filters. I've sometimes wanted the multiple-value case, though I've so
far been able to work around its lack. TODO: Perhaps it would also make sense to have a
`Caveat` map an *event* to zero or more *events*, rather than to values? Tricky corners
there include ensuring that carried authority isn't misused; macaroons are a very elegant
solution to this problem, of course, so maybe the macaroon design idea could be adapted to
this. For now, `Value`→`Option<Value>` is probably OK.
[^affine-caveats]: `Caveat`s are thus *affine*.
[^single-rewrite-meaning]: A single `Rewrite` *R* is equivalent to `<or [`*R*`]>`.

View File

@ -25,16 +25,28 @@ an overview of `SturdyRef`s, see the [guide to the built-in gatekeeper
entity](../../operation/builtin/gatekeeper.md#sturdyrefs).
```
SturdyRef = <ref @oid any @caveatChain [Attenuation ...] @sig bytes>.
SturdyRef = <ref @oid any @caveatChain [Caveat ...] @sig bytes>.
```
For detail of the interpretation of `Attenuation`s, `Caveat`s, `Pattern`s, and `Template`s, see
the [Syndicate protocol specification](../../protocol.md#capabilities-on-the-wire).
The `sig` in a `SturdyRef` is an iterated keyed-HMAC construction, starting from an HMAC of the
ref's *secret key* and its `oid`, following [macaroons][]. The specific function chosen is
[HMAC](https://www.rfc-editor.org/rfc/rfc2104) using
[BLAKE2s-256](https://www.rfc-editor.org/rfc/rfc7693), truncating the output to the first 16
bytes. Let
- *f(k,d)* be `HMAC-BLAKE2s-256`*(k,d)*[0..16),
- *e(v)* yield the canonical machine-oriented serialization of some preserves value *v*, and
- *k* be the original secret key for the ref.
In a valid `SturdyRef`, then, the `sig` will be *f(...f(...f(f(k,e(*`oid`*)),...),e(*`Caveat`*)),...)*.
For detail of the interpretation of `Caveat`s, `Pattern`s, and `Template`s, see the [Syndicate
protocol specification](../../protocol.md#capabilities-on-the-wire).
```
Attenuation = [Caveat ...].
Caveat = Rewrite / Alts .
Rewrite = <rewrite @pattern Pattern @template Template>.
Caveat = Rewrite / Alts / Reject / @unknown any .
Rewrite = <rewrite @pattern Pattern @template Template> .
Reject = <reject @pattern Pattern> .
Alts = <or @alternatives [Rewrite ...]>.
Lit = <lit @value any>.
@ -52,10 +64,12 @@ PCompound =
/ @dict <dict @entries { any: Pattern ...:... }> .
Template = TAttenuate / TRef / Lit / TCompound .
TAttenuate = <attenuate @template Template @attenuation Attenuation>.
TAttenuate = <attenuate @template Template @attenuation [Caveat ...]>.
TRef = <ref @binding int>.
TCompound =
/ @rec <rec @label any @fields [Template ...]>
/ @arr <arr @items [Template ...]>
/ @dict <dict @entries { any: Template ...:... }> .
```
[Macaroons]: ../../glossary.md#macaroon