Flesh out state updates

This commit is contained in:
Nadja Reitzenstein 2022-11-01 11:54:01 +01:00
parent b5f5a4981f
commit d5d07a1203
9 changed files with 113 additions and 79 deletions

View File

@ -3,8 +3,8 @@
using CSharp = import "programming_language/csharp.capnp";
$CSharp.namespace("FabAccessAPI.Schema");
using L10NString = import "utils.capnp".L10NString;
using Session = import "main.capnp".Session;
using import "utils.capnp".L10NString;
using import "main.capnp".Session;
struct Response {
enum Reason {

View File

@ -7,6 +7,7 @@ using import "/capnp/rpc.capnp".SturdyRef;
using import "persistent.capnp".Persistent;
using import "state.capnp".State;
using import "state.capnp".Update;
interface Claimable extends (Persistent) {
restore @0 ( sturdy :SturdyRef ) -> ( claim :Claim );
@ -18,5 +19,19 @@ interface Claimable extends (Persistent) {
}
interface Claim extends (Persistent) {
update @0 ( state :State ) -> ();
update @0 ( update :Update ) -> ( error :Error );
# Transactionally update a resource via a claim.
#
# The parameter `update` is a list of `UpdateValue` that specify a list of behaviours to be
# updated with the associated data. The format of this data depends on and is defined by the
# behaviour.
# An update call is atomic and transactional, if any one of the UpdateValue can not be applied
# the entire update call fails and is not applied. A client may send multiple update calls in
# parallel to opt out of the transactional behaviour of update. The ordering in which multiple
# update calls are applied is not specified, a client MUST NOT rely on updates happening in the
# order they are sent.
# The returned `error` is NULL if the update call succeeded.
interface Error {
}
}

View File

@ -3,9 +3,9 @@
using CSharp = import "programming_language/csharp.capnp";
$CSharp.namespace("FabAccessAPI.Schema");
using Authentication = import "auth.capnp".Authentication;
using Resources = import "resources.capnp".Resources;
using Users = import "users.capnp".Users;
using import "auth.capnp".Authentication;
using import "resources.capnp".Resources;
using import "users.capnp".Users;
struct Version
{
@ -18,9 +18,8 @@ interface Bootstrap
getAPIVersion @0 () -> Version;
getServerRelease @1 () -> ( name :Text, release :Text );
# Returns the server implementation name and version/build number
# Designed only for human-facing debugging output so should be informative
# over machine-readable.
# Returns the server implementation name and version/build number Designed only for human-facing
# debugging output so should be informative over machine-readable.
# Example: ("bffhd", "0.3.1-f397e1e [rustc 1.57.0 (f1edd0429 2021-11-29)]")
mechanisms @2 () -> ( mechs :List(Text) );
@ -28,22 +27,21 @@ interface Bootstrap
createSession @3 ( mechanism :Text, initialData :Data )
-> ( authentication :Authentication );
# Create a new session with the server that you wish to authenticate using
# `mechanism`. If the mechanism is a client-first mechanism you MAY set
# `initialData` to contain the data you want to send. If the mechanism is
# server-first or you do not wish to send initial data, make initialData a
# NULL-pointer.
# Create a new session with the server that you wish to authenticate using `mechanism`. If the
# mechanism is a client-first mechanism you MAY set `initialData` to contain the data you want
# to send. If the mechanism is server-first or you do not wish to send initial data, make
# initialData a NULL-pointer.
}
struct Session {
# An API session with the server. The below capabilities are set to NULL if
# the authenticated user doesn't have permission to access the system in
# question, or if the server does not implement it.
# An API session with the server. The below capabilities are set to NULL if the authenticated
# user doesn't have permission to access the system in question, or if the server does not
# implement it.
resources @0 :Resources;
# Access to the resources configured.
users @1 :Users;
# User administration. This includes both modifying other users and
# self-modification, so this is allowed for most sessions
# User administration. This includes both modifying other users and self-modification, so this
# is allowed for most sessions
}

View File

@ -3,14 +3,26 @@
using CSharp = import "programming_language/csharp.capnp";
$CSharp.namespace("FabAccessAPI.Schema");
using State = import "state.capnp".State;
using import "state.capnp".State;
using import "state.capnp".Update;
interface Notifyable {
subscribe @0 ( subscriber :Subscriber ) -> ( subscription :Subscription );
state @0 () -> ( state :State );
# Returns the current state of a resource.
subscribe @1 ( subscriber :Subscriber ) -> ( subscription :Subscription );
# Subscribe to state updates. The passed in `subscriber` is an interface implemented on the
# client side that a server calls to send update notifications.
}
interface Subscriber {
newState @0 ( state :State ) -> ();
update @0 ( update :Update ) -> ();
# Called by a server when a new state was produced for this resource. This method MAY not be
# called when a resource was updated but did not change its state. A server will only ever have
# one running update call per client session, so a client can limit the rate of updates by not
# resolving this call immediately. A server will coalesce multiple updates into a single update
# notification, meaning a client is not guaranteed to receive every intermediary state for a
# resource.
}
interface Subscription { }

View File

@ -11,23 +11,31 @@ using import "claim.capnp".Claimable;
using import "utils.capnp".OID;
interface Resource extends (Persistent) {
# BFFH's smallest unit of a physical or abstract "thing". A resource can be
# as simple and physical as a table, as complex as a PCB production line or
# as abstract as "people with specific know-how are present".
# BFFH's smallest unit of a physical or abstract "thing". A resource can be as simple and
# physical as a table, as complex as a PCB production line or as abstract as "people with
# specific know-how are present".
type @0 () -> ( types :List(OID) );
# The 'type' of Resource. Each OID in the list specifies certain behaviours
# that this Resource follows.
# The 'type' of Resource. Each OID in the list specifies certain behaviours that this Resource
# follows.
notify @1 () -> ( notify :Notifyable );
# NULL if the user does not have permission to read this resource, or if
# this resource is not notifiable
describe @1 () -> Description;
# Return information about this resource. This information is usually rather static, but may
# change between calls.
interest @2 () -> ( interest :Interestable );
# NULL if this resource is not interestable or the user does not have
# permission to set interests for this resource.
notify @2 () -> ( notify :Notifyable );
# NULL if the user does not have permission to read this resource, or if this resource is not
# notifiable
interest @3 () -> ( interest :Interestable );
# NULL if this resource is not interestable or the user does not have permission to set
# interests for this resource.
claim @4 () -> ( claim :Claimable );
# NULL if the user does not have permission to write to this resource, or if this resource is
# not (ever!) claimable
}
struct Description {
claim @3 () -> ( claim :Claimable );
# NULL if the user does not have permission to write to this resource, or if
# this resource is not (ever!) claimable
}

View File

@ -5,7 +5,7 @@ $CSharp.namespace("FabAccessAPI.Schema");
using import "/capnp/rpc.capnp".SturdyRef;
using Resource = import "resource.capnp".Resource;
using import "resource.capnp".Resource;
interface Resources {
restore @0 ( sturdy :SturdyRef ) -> ( resources :Resource );
@ -14,8 +14,8 @@ interface Resources {
list @1 () -> ( resources :List(Resource) );
getByUrn @2 ( urn :Text ) -> ( resource :Resource );
# Returns a NULL capability if the resource doesn't exist or an user
# doesn't have disclose permission for that resource.
# Returns a NULL capability if the resource doesn't exist or an user doesn't have disclose
# permission for that resource.
getByName @3 ( name :Text ) -> ( resource :Resource );
}

View File

@ -3,6 +3,15 @@
using CSharp = import "programming_language/csharp.capnp";
$CSharp.namespace("FabAccessAPI.Schema");
interface State {
using import "utils.capnp".OID;
interface State {
get @0 ( oid :OID ) -> ( val :AnyPointer );
}
struct UpdateValue {
oid @0 :OID;
val @1 :AnyPointer;
}
using Update = List(UpdateValue);

View File

@ -3,7 +3,7 @@
using CSharp = import "programming_language/csharp.capnp";
$CSharp.namespace("FabAccessAPI.Schema");
using User = import "user.capnp".User;
using import "user.capnp".User;
interface Users {
whoami @0 () -> ( user :User );

View File

@ -1,41 +1,35 @@
@0xed0c02f41fea6b5a;
interface L10NString {
# Any string type that is intended to be displayed to an user that is more
# than an identifier to be used as-is must be able to be localized into the
# users preferred language. This includes description, help messages, etc.
# but of course does not extend to usernames.
# TODO: Potentially make generic over the localized content (e.g. dates)?
# Can be done after the fact without braking protocol, so no big issue.
# Any string type that is intended to be displayed to an user that is more than an identifier to
# be used as-is must be able to be localized into the users preferred language. This includes
# description, help messages, etc. but of course does not extend to usernames.
# TODO: Potentially make generic over the localized content (e.g. dates)? Can be done after the
# fact without braking protocol, so no big issue.
get @0 ( lang :Text ) -> ( lang :Text, content :Text );
# Retrieve the string in the given locale. The input parameter MUST be a
# RFC5646-formatted locale identifier (e.g: "en-US", "de-DE", "az-Arab-IR").
# Retrieve the string in the given locale. The input parameter MUST be a RFC5646-formatted
# locale identifier (e.g: "en-US", "de-DE", "az-Arab-IR").
#
# If a server can't find a localized version matching exactly it MUST try to
# substitute it. Substitution MUST always return more specific matches for
# general queries. e.g. if "it" is requested and the server has "it-CH"
# available it returns this string.
# If a server can't find a localized version matching exactly it MUST try to substitute it.
# Substitution MUST always return more specific matches for general queries. e.g. if "it" is
# requested and the server has "it-CH" available it returns this string.
#
# Substitution SHOULD NOT cross language barriers, e.g. returning "en-GB"
# for a string requested in "cy-GB". Substitution MUST NOT return a
# localization in a different language unless server has a priori knowledge
# that the user can read and understand said language.
# Substitution SHOULD NOT cross language barriers, e.g. returning "en-GB" for a string requested
# in "cy-GB". Substitution MUST NOT return a localization in a different language unless server
# has a priori knowledge that the user can read and understand said language.
#
# Substitution SHOULD prefer unspecified subtags over wrong subtags. If
# "es-AR" is requested and a server has "es", and "es-VE" available, "es"
# should be selected.
# Substitution SHOULD prefer unspecified subtags over wrong subtags. If "es-AR" is requested and
# a server has "es", and "es-VE" available, "es" should be selected.
#
# A server MUST set the output `lang` field to the exact tag that the
# content it sends was written in and `content` to the localized string.
# e.g. If a string is requested for "sr" and the server has found a string
# that was configured as "sr-Cyrl-BA" the server sets lang to "sr-Cyrl-BA".
# A server MUST set the output `lang` field to the exact tag that the content it sends was
# written in and `content` to the localized string. e.g. If a string is requested for "sr" and
# the server has found a string that was configured as "sr-Cyrl-BA" the server sets lang to
# "sr-Cyrl-BA".
#
# If a server can't find a suitable substitute it MUST set the output
# `content` to a NULL pointer and set the output `lang` to the input `lang`
# it was passed.
# If a server can't parse a given `lang` tag it MUST set the output `lang`
# to NULL.
# If a server can't find a suitable substitute it MUST set the output `content` to a NULL
# pointer and set the output `lang` to the input `lang` it was passed.
# If a server can't parse a given `lang` tag it MUST set the output `lang` to NULL.
available @1 () -> ( langs :List(Text) );
# Returns the list of locales this content is available in.
@ -59,13 +53,11 @@ struct UUID {
}
using OID = Data;
# An OID is encoded as a sequence of varints. In this encoding the lower 7 bits
# of each octet contain data bits while the MSB indicates if the *following*
# octet is still part of this edge. It is the same encoding UTF-8 uses. To
# decode you simply collect octets until you find an octet <128 and then concat
# the data bits of all the octets you've accumulated, including the current one.
# This gives you the value of one node. Continue until you've exhausted the
# available data. This is a rather efficient encoding since almost all edges of
# the OID tree are smaller than 128 and thus encode into one byte.
# X.208 does *not* limit the size of nodes! However, a reasonable size limit is
# 128 bit per node, which is the size of the UUID nodes in the `2.25` subtree.
# An OID is encoded as a sequence of varints. In this encoding the lower 7 bits of each octet
# contain data bits while the MSB indicates if the *following* octet is still part of this edge. It
# is the same encoding UTF-8 uses. To decode you simply collect octets until you find an octet <128
# and then concat the data bits of all the octets you've accumulated, including the current one.
# This gives you the value of one node. Continue until you've exhausted the available data. This is
# a rather efficient encoding since almost all edges of the OID tree are smaller than 128 and thus
# encode into one byte. X.208 does *not* limit the size of nodes! However, a reasonable size limit
# is 128 bit per node, which is the size of the UUID nodes in the `2.25` subtree.