mirror of
https://gitlab.com/fabinfra/fabaccess/fabaccess-api.git
synced 2025-03-12 23:01:47 +01:00
Flesh out state updates
This commit is contained in:
parent
b5f5a4981f
commit
d5d07a1203
@ -3,8 +3,8 @@
|
|||||||
using CSharp = import "programming_language/csharp.capnp";
|
using CSharp = import "programming_language/csharp.capnp";
|
||||||
$CSharp.namespace("FabAccessAPI.Schema");
|
$CSharp.namespace("FabAccessAPI.Schema");
|
||||||
|
|
||||||
using L10NString = import "utils.capnp".L10NString;
|
using import "utils.capnp".L10NString;
|
||||||
using Session = import "main.capnp".Session;
|
using import "main.capnp".Session;
|
||||||
|
|
||||||
struct Response {
|
struct Response {
|
||||||
enum Reason {
|
enum Reason {
|
||||||
|
17
claim.capnp
17
claim.capnp
@ -7,6 +7,7 @@ using import "/capnp/rpc.capnp".SturdyRef;
|
|||||||
|
|
||||||
using import "persistent.capnp".Persistent;
|
using import "persistent.capnp".Persistent;
|
||||||
using import "state.capnp".State;
|
using import "state.capnp".State;
|
||||||
|
using import "state.capnp".Update;
|
||||||
|
|
||||||
interface Claimable extends (Persistent) {
|
interface Claimable extends (Persistent) {
|
||||||
restore @0 ( sturdy :SturdyRef ) -> ( claim :Claim );
|
restore @0 ( sturdy :SturdyRef ) -> ( claim :Claim );
|
||||||
@ -18,5 +19,19 @@ interface Claimable extends (Persistent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Claim 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 {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
30
main.capnp
30
main.capnp
@ -3,9 +3,9 @@
|
|||||||
using CSharp = import "programming_language/csharp.capnp";
|
using CSharp = import "programming_language/csharp.capnp";
|
||||||
$CSharp.namespace("FabAccessAPI.Schema");
|
$CSharp.namespace("FabAccessAPI.Schema");
|
||||||
|
|
||||||
using Authentication = import "auth.capnp".Authentication;
|
using import "auth.capnp".Authentication;
|
||||||
using Resources = import "resources.capnp".Resources;
|
using import "resources.capnp".Resources;
|
||||||
using Users = import "users.capnp".Users;
|
using import "users.capnp".Users;
|
||||||
|
|
||||||
struct Version
|
struct Version
|
||||||
{
|
{
|
||||||
@ -18,9 +18,8 @@ interface Bootstrap
|
|||||||
getAPIVersion @0 () -> Version;
|
getAPIVersion @0 () -> Version;
|
||||||
|
|
||||||
getServerRelease @1 () -> ( name :Text, release :Text );
|
getServerRelease @1 () -> ( name :Text, release :Text );
|
||||||
# Returns the server implementation name and version/build number
|
# Returns the server implementation name and version/build number Designed only for human-facing
|
||||||
# Designed only for human-facing debugging output so should be informative
|
# debugging output so should be informative over machine-readable.
|
||||||
# over machine-readable.
|
|
||||||
# Example: ("bffhd", "0.3.1-f397e1e [rustc 1.57.0 (f1edd0429 2021-11-29)]")
|
# Example: ("bffhd", "0.3.1-f397e1e [rustc 1.57.0 (f1edd0429 2021-11-29)]")
|
||||||
|
|
||||||
mechanisms @2 () -> ( mechs :List(Text) );
|
mechanisms @2 () -> ( mechs :List(Text) );
|
||||||
@ -28,22 +27,21 @@ interface Bootstrap
|
|||||||
|
|
||||||
createSession @3 ( mechanism :Text, initialData :Data )
|
createSession @3 ( mechanism :Text, initialData :Data )
|
||||||
-> ( authentication :Authentication );
|
-> ( authentication :Authentication );
|
||||||
# Create a new session with the server that you wish to authenticate using
|
# Create a new session with the server that you wish to authenticate using `mechanism`. If the
|
||||||
# `mechanism`. If the mechanism is a client-first mechanism you MAY set
|
# mechanism is a client-first mechanism you MAY set `initialData` to contain the data you want
|
||||||
# `initialData` to contain the data you want to send. If the mechanism is
|
# to send. If the mechanism is server-first or you do not wish to send initial data, make
|
||||||
# server-first or you do not wish to send initial data, make initialData a
|
# initialData a NULL-pointer.
|
||||||
# NULL-pointer.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Session {
|
struct Session {
|
||||||
# An API session with the server. The below capabilities are set to NULL if
|
# An API session with the server. The below capabilities are set to NULL if the authenticated
|
||||||
# the authenticated user doesn't have permission to access the system in
|
# user doesn't have permission to access the system in question, or if the server does not
|
||||||
# question, or if the server does not implement it.
|
# implement it.
|
||||||
|
|
||||||
resources @0 :Resources;
|
resources @0 :Resources;
|
||||||
# Access to the resources configured.
|
# Access to the resources configured.
|
||||||
|
|
||||||
users @1 :Users;
|
users @1 :Users;
|
||||||
# User administration. This includes both modifying other users and
|
# User administration. This includes both modifying other users and self-modification, so this
|
||||||
# self-modification, so this is allowed for most sessions
|
# is allowed for most sessions
|
||||||
}
|
}
|
||||||
|
18
notify.capnp
18
notify.capnp
@ -3,14 +3,26 @@
|
|||||||
using CSharp = import "programming_language/csharp.capnp";
|
using CSharp = import "programming_language/csharp.capnp";
|
||||||
$CSharp.namespace("FabAccessAPI.Schema");
|
$CSharp.namespace("FabAccessAPI.Schema");
|
||||||
|
|
||||||
using State = import "state.capnp".State;
|
using import "state.capnp".State;
|
||||||
|
using import "state.capnp".Update;
|
||||||
|
|
||||||
interface Notifyable {
|
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 {
|
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 { }
|
interface Subscription { }
|
||||||
|
@ -11,23 +11,31 @@ using import "claim.capnp".Claimable;
|
|||||||
using import "utils.capnp".OID;
|
using import "utils.capnp".OID;
|
||||||
|
|
||||||
interface Resource extends (Persistent) {
|
interface Resource extends (Persistent) {
|
||||||
# BFFH's smallest unit of a physical or abstract "thing". A resource can be
|
# BFFH's smallest unit of a physical or abstract "thing". A resource can be as simple and
|
||||||
# as simple and physical as a table, as complex as a PCB production line or
|
# physical as a table, as complex as a PCB production line or as abstract as "people with
|
||||||
# as abstract as "people with specific know-how are present".
|
# specific know-how are present".
|
||||||
|
|
||||||
type @0 () -> ( types :List(OID) );
|
type @0 () -> ( types :List(OID) );
|
||||||
# The 'type' of Resource. Each OID in the list specifies certain behaviours
|
# The 'type' of Resource. Each OID in the list specifies certain behaviours that this Resource
|
||||||
# that this Resource follows.
|
# follows.
|
||||||
|
|
||||||
notify @1 () -> ( notify :Notifyable );
|
describe @1 () -> Description;
|
||||||
# NULL if the user does not have permission to read this resource, or if
|
# Return information about this resource. This information is usually rather static, but may
|
||||||
# this resource is not notifiable
|
# change between calls.
|
||||||
|
|
||||||
interest @2 () -> ( interest :Interestable );
|
notify @2 () -> ( notify :Notifyable );
|
||||||
# NULL if this resource is not interestable or the user does not have
|
# NULL if the user does not have permission to read this resource, or if this resource is not
|
||||||
# permission to set interests for this resource.
|
# 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
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ $CSharp.namespace("FabAccessAPI.Schema");
|
|||||||
|
|
||||||
using import "/capnp/rpc.capnp".SturdyRef;
|
using import "/capnp/rpc.capnp".SturdyRef;
|
||||||
|
|
||||||
using Resource = import "resource.capnp".Resource;
|
using import "resource.capnp".Resource;
|
||||||
|
|
||||||
interface Resources {
|
interface Resources {
|
||||||
restore @0 ( sturdy :SturdyRef ) -> ( resources :Resource );
|
restore @0 ( sturdy :SturdyRef ) -> ( resources :Resource );
|
||||||
@ -14,8 +14,8 @@ interface Resources {
|
|||||||
list @1 () -> ( resources :List(Resource) );
|
list @1 () -> ( resources :List(Resource) );
|
||||||
|
|
||||||
getByUrn @2 ( urn :Text ) -> ( resource :Resource );
|
getByUrn @2 ( urn :Text ) -> ( resource :Resource );
|
||||||
# Returns a NULL capability if the resource doesn't exist or an user
|
# Returns a NULL capability if the resource doesn't exist or an user doesn't have disclose
|
||||||
# doesn't have disclose permission for that resource.
|
# permission for that resource.
|
||||||
|
|
||||||
getByName @3 ( name :Text ) -> ( resource :Resource );
|
getByName @3 ( name :Text ) -> ( resource :Resource );
|
||||||
}
|
}
|
||||||
|
11
state.capnp
11
state.capnp
@ -3,6 +3,15 @@
|
|||||||
using CSharp = import "programming_language/csharp.capnp";
|
using CSharp = import "programming_language/csharp.capnp";
|
||||||
$CSharp.namespace("FabAccessAPI.Schema");
|
$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);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
using CSharp = import "programming_language/csharp.capnp";
|
using CSharp = import "programming_language/csharp.capnp";
|
||||||
$CSharp.namespace("FabAccessAPI.Schema");
|
$CSharp.namespace("FabAccessAPI.Schema");
|
||||||
|
|
||||||
using User = import "user.capnp".User;
|
using import "user.capnp".User;
|
||||||
|
|
||||||
interface Users {
|
interface Users {
|
||||||
whoami @0 () -> ( user :User );
|
whoami @0 () -> ( user :User );
|
||||||
|
68
utils.capnp
68
utils.capnp
@ -1,41 +1,35 @@
|
|||||||
@0xed0c02f41fea6b5a;
|
@0xed0c02f41fea6b5a;
|
||||||
|
|
||||||
interface L10NString {
|
interface L10NString {
|
||||||
# Any string type that is intended to be displayed to an user that is more
|
# Any string type that is intended to be displayed to an user that is more than an identifier to
|
||||||
# than an identifier to be used as-is must be able to be localized into the
|
# be used as-is must be able to be localized into the users preferred language. This includes
|
||||||
# users preferred language. This includes description, help messages, etc.
|
# description, help messages, etc. but of course does not extend to usernames.
|
||||||
# but of course does not extend to usernames.
|
# TODO: Potentially make generic over the localized content (e.g. dates)? Can be done after the
|
||||||
# TODO: Potentially make generic over the localized content (e.g. dates)?
|
# fact without braking protocol, so no big issue.
|
||||||
# Can be done after the fact without braking protocol, so no big issue.
|
|
||||||
|
|
||||||
get @0 ( lang :Text ) -> ( lang :Text, content :Text );
|
get @0 ( lang :Text ) -> ( lang :Text, content :Text );
|
||||||
# Retrieve the string in the given locale. The input parameter MUST be a
|
# Retrieve the string in the given locale. The input parameter MUST be a RFC5646-formatted
|
||||||
# RFC5646-formatted locale identifier (e.g: "en-US", "de-DE", "az-Arab-IR").
|
# 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
|
# If a server can't find a localized version matching exactly it MUST try to substitute it.
|
||||||
# substitute it. Substitution MUST always return more specific matches for
|
# Substitution MUST always return more specific matches for general queries. e.g. if "it" is
|
||||||
# general queries. e.g. if "it" is requested and the server has "it-CH"
|
# requested and the server has "it-CH" available it returns this string.
|
||||||
# available it returns this string.
|
|
||||||
#
|
#
|
||||||
# Substitution SHOULD NOT cross language barriers, e.g. returning "en-GB"
|
# Substitution SHOULD NOT cross language barriers, e.g. returning "en-GB" for a string requested
|
||||||
# for a string requested in "cy-GB". Substitution MUST NOT return a
|
# in "cy-GB". Substitution MUST NOT return a localization in a different language unless server
|
||||||
# localization in a different language unless server has a priori knowledge
|
# has a priori knowledge that the user can read and understand said language.
|
||||||
# that the user can read and understand said language.
|
|
||||||
#
|
#
|
||||||
# Substitution SHOULD prefer unspecified subtags over wrong subtags. If
|
# Substitution SHOULD prefer unspecified subtags over wrong subtags. If "es-AR" is requested and
|
||||||
# "es-AR" is requested and a server has "es", and "es-VE" available, "es"
|
# a server has "es", and "es-VE" available, "es" should be selected.
|
||||||
# should be selected.
|
|
||||||
#
|
#
|
||||||
# A server MUST set the output `lang` field to the exact tag that the
|
# A server MUST set the output `lang` field to the exact tag that the content it sends was
|
||||||
# content it sends was written in and `content` to the localized string.
|
# written in and `content` to the localized string. e.g. If a string is requested for "sr" and
|
||||||
# e.g. If a string is requested for "sr" and the server has found a string
|
# the server has found a string that was configured as "sr-Cyrl-BA" the server sets lang to
|
||||||
# that was configured as "sr-Cyrl-BA" the server sets lang to "sr-Cyrl-BA".
|
# "sr-Cyrl-BA".
|
||||||
#
|
#
|
||||||
# If a server can't find a suitable substitute it MUST set the output
|
# If a server can't find a suitable substitute it MUST set the output `content` to a NULL
|
||||||
# `content` to a NULL pointer and set the output `lang` to the input `lang`
|
# pointer and set the output `lang` to the input `lang` it was passed.
|
||||||
# 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 parse a given `lang` tag it MUST set the output `lang`
|
|
||||||
# to NULL.
|
|
||||||
|
|
||||||
available @1 () -> ( langs :List(Text) );
|
available @1 () -> ( langs :List(Text) );
|
||||||
# Returns the list of locales this content is available in.
|
# Returns the list of locales this content is available in.
|
||||||
@ -59,13 +53,11 @@ struct UUID {
|
|||||||
}
|
}
|
||||||
|
|
||||||
using OID = Data;
|
using OID = Data;
|
||||||
# An OID is encoded as a sequence of varints. In this encoding the lower 7 bits
|
# An OID is encoded as a sequence of varints. In this encoding the lower 7 bits of each octet
|
||||||
# of each octet contain data bits while the MSB indicates if the *following*
|
# contain data bits while the MSB indicates if the *following* octet is still part of this edge. It
|
||||||
# octet is still part of this edge. It is the same encoding UTF-8 uses. To
|
# is the same encoding UTF-8 uses. To decode you simply collect octets until you find an octet <128
|
||||||
# decode you simply collect octets until you find an octet <128 and then concat
|
# and then concat the data bits of all the octets you've accumulated, including the current one.
|
||||||
# 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
|
||||||
# This gives you the value of one node. Continue until you've exhausted the
|
# a rather efficient encoding since almost all edges of the OID tree are smaller than 128 and thus
|
||||||
# available data. This is a rather efficient encoding since almost all edges of
|
# encode into one byte. X.208 does *not* limit the size of nodes! However, a reasonable size limit
|
||||||
# the OID tree are smaller than 128 and thus encode into one byte.
|
# is 128 bit per node, which is the size of the UUID nodes in the `2.25` subtree.
|
||||||
# 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.
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user