# Gatekeeper When `syndicate-server` starts, it creates a *gatekeeper service entity*, which accepts `resolve` assertions requesting conversion of a long-lived credential to a [live reference](../../glossary.md#reference). The gatekeeper is the [default object](../../glossary.md#initial-ref), available as [OID](../../glossary.md#oid) 0 to peers at the other end of [relay listener](./relay-listener.md) connections. ## Gatekeeper protocol - Relevant schema: [[syndicate-protocol]/schemas/gatekeeper.prs](https://git.syndicate-lang.org/syndicate-lang/syndicate-protocols/src/branch/main/schemas/gatekeeper.prs) ```preserves-schema Resolve = . Resolved = / Rejected . Step = < @stepType symbol [@detail any]> . Rejected = . ``` When a request to resolve a given credential, a `Step`, appears, the gatekeeper entity queries a dataspace (by default, the server's top-level `$config` dataspace) for `bind` assertions: ```preserves-schema Bind = . Description = < @stepType symbol [@detail any]> . BindObserver = @present #:Bound / @absent #f . Bound = / Rejected . ``` A `bind` assertion specifies the reference that backs a long-lived credential, and gives instructions for checking the validity of a presented credential. Each `bind` assertion matching a requested `Step` is checked using the `stepType`-specific `detail` in the `Description` combined with the `detail` from the `Step`. If the checks pass, the `target` entity from the `bind` is asserted in an `accepted` record to the `observer` in the `resolve`. If the checks fail, a `rejected` record is asserted to the `observer`. If no `bind` matching a particular `Step` exists, the system just waits; this allows it to be relaxed about ordering of events. However, besides waiting for a `bind`, the gatekeeper asserts a `resolve` of its own into its associated dataspace, with the same `Step` that it received but a different `observer`. If, before an appropriate `bind` appears, a `Resolved` assertion is sent to this `resolve`'s `observer`, the gatekeeper stops waiting for a `bind` and relays the response on to the ultimate requester directly. This way, entities can keep an eye out for `resolve` requests that will never complete, and answer `rejected` to them even when no matching `bind` exists. Entities can also use `resolve` requests to synthesize a `bind` in a "just-in-time" fashion. ## Sturdyrefs - Relevant schema: [[syndicate-protocol]/schemas/sturdy.prs](https://git.syndicate-lang.org/syndicate-lang/syndicate-protocols/src/branch/main/schemas/sturdy.prs) A "sturdyref" is a long-lived certificate including a cryptographic signature that can be upgraded by a gatekeeper entity to a live reference to the entity named in the sturdyref. The current sturdyref implementation is based on the design of [Macaroons][]. **Example.** The sturdyref `` is valid for the associated `Bind` assertion ` $ds #f>`. The following definitions are taken from the [sturdy.prs](https://git.syndicate-lang.org/syndicate-lang/syndicate-protocols/src/branch/main/schemas/sturdy.prs) schema. For further detail, see the [reference](../../protocols/syndicate/gatekeeper.md). ```preserves-schema SturdyStepType = =ref . SturdyStepDetail = Parameters . SturdyRef = . ``` First, when used as a `Step`, a sturdyref uses `ref` as its `stepType` and `Parameters` as its `detail`. A sturdyref as a whole, then, is just the combination of the type and parameters in a record. ```preserves-schema Parameters = { oid: any, sig: bytes, } & @caveats CaveatsField . CaveatsField = / @present { caveats: [Caveat ...] } / @invalid { caveats: any } / @absent {} . ``` The `Parameters` of a sturdyref are the `oid` field, which is a free-form value that the targeted service chooses to name itself, and the `sig`, which is an iterated keyed-HMAC construction, just as in [macaroons][]. The `sig` is derived from the `oid` and the service's secret `key`: ```preserves-schema SturdyDescriptionDetail = { oid: any, key: bytes, } . ``` In a `Bind` with `stepType` of `ref`, the `detail` in the `Description` should be a `SturdyDescriptionDetail` value. The `key` is the secret key used to compute `sig`s on sturdyrefs; the `oid` connects references with their defining `Bind`s. To compute a `sig` for a sturdyref, the service's secret key is first used to key an HMAC of the `oid`. Then, the result is used to key an HMAC of the ([canonical form](../../guide/preserves.md#canonical-form) of the) first `Caveat` in the ref's `caveats`, if any. Each `Caveat`'s HMAC becomes the key for the next in the `caveatChain`. The `sig` is the final result. When validating sturdyrefs, compute the `sig` fresh, starting from the `key` and `oid`, and compare the final result to the presented `sig`. ### Attenuation of authority When it comes to publishing assertions or sending messages to the entity denoted by a sturdyref, the `caveatChain` is used to [attenuate](../../glossary.md#attenuation) the 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. 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