syntax = "proto3";
package com.github.oslokommune.oslonokkelen.adapter.proto;
// The role of the manifest is to describe what the adapter can
// do and the state things are in right now.
message AdapterManifest {
// Can be used to optimize scraping. Backend can pass last known version
// when scraping and if nothing has changed the adapter is allowed to return
// an empty 304 not modified response to avoid re-transferring the same data
// Oslonøkkelen already knows.
int64 version = 1;
// Collection of doors, lamps...
repeated Thing things = 2;
// Declaration of errors might returned from the adapter.
// By declaring error possible error codes up front administrators of
// Oslonøkkelen can write and change human readable messages for different
// errors without changing the implementation of the adapter.
repeated ErrorCodeDescription error_code_descriptions = 3;
// Examples:
// * front-door
// * outdoor-lighting
message Thing {
// Url safe id
string id = 1;
// Short one line description of what it does
string description = 2;
// Optional.
// Determines who can administer this thing in Oslonøkkelen key studio.
string admin_role = 3;
reserved 4;
// What the thing can do
repeated Action actions = 5;
// Some things are equipped with sensors allowing us to observe state like
// locked, unlocked, open, close, offline, online etc. Implementing this can
// help administrators of Oslonøkkelen to configure alerts when things go
// offline, remain open too long etc.
repeated ThingState state = 6;
}
// Examples:
// * unlock
// * open
message Action {
// Url safe id
string id = 1;
// Short one line description of what it does
string description = 2;
// Required input attachments.
// Example: The public service Gjenbruksid requires the users ssn to work.
repeated AttachmentType required_input_attachment_types = 3;
// Possible output
repeated AttachmentType possible_output_attachment_types = 4;
reserved 5;
}
// Example
// -------
// Code: offline
// Description: System x has been offline for y hours
message ErrorCodeDescription {
// Url safe code.
string code = 1;
// Really short human readable description explaining
// when this code will be returned.
string description = 2;
}
}
// Will be submitted to the /execute endpoint.
message ActionRequest {
// Useful for correlation of requests across systems
string request_id = 5;
// Identifies a thing in the manifest
// Example: front-door
string thing_id = 1;
// Identifies an action associated with the thing.
// Example: open
string action_id = 2;
// Most action request won't have any attachments as most
// adapters have no need to know who executed an action.
repeated Attachment attachments = 3;
// The app will have enforce a timeout. The adapter should try
// hard to return within this time budget. Returning a timeout
// error is better then not returning anything.
int32 time_budget_millis = 4;
}
// Your adapter should return this as a response to requests submitted
// to the /execute endpoint _after_ the adapter is done executing the action.
message ActionResponse {
// Indicates whether the action succeeded or not.
Status status = 1;
// Any attachments produced by the action.
//
// Example: By returning the `ErrorDescription` after an error you can make
// troubleshooting a lot easier for administrators of Oslonøkkelen.
repeated Attachment attachments = 2;
enum Status {
// All good!
SUCCESS = 0;
// Something really crashed bad..
// No need to automatically try again.
ERROR_PERMANENT = 1;
// Something like temporary network exceptions.
// Automatic retry might work!
ERROR_TEMPORARY = 2;
// Access denied.
// No need retrying with the same input.
DENIED = 3;
}
}
// Different actions can require certain input
enum AttachmentType {
// Request attachment.
// Useful for authorization.
// Try to avoid depending on this if possible as it comes
// with a lot of GDPR related requirements.
NORWEGIAN_FODSELSNUMMER = 0;
// Response attachment. Useful for sending something like a
// member number to users of Oslonøkkelen.
CODE = 1;
reserved 2;
// Response attachment.
// Allows the adapter to send a human readable message back
// to the user of the app responsible for issuing the request.
END_USER_MESSAGE = 3;
// Response attachment.
// Technical error information useful for debugging and troubleshooting.
ERROR_DESCRIPTION = 4;
// Response attachment.
// Technical information explaining why an action request was denied.
// Should only be used for action responses with status = denied.
DENIED_REASON = 5;
}
// Action requests and responses can contain attachments.
message Attachment {
oneof value {
// Can be used to return things like membership numbers.
// The app has optional support for formatting qr and barcodes.
Code code = 1;
// Technical error description used for logging and debugging.
// This won't be displayed to the end user of the app.
ErrorDescription error_description = 3;
// The content of this will be displayed to the end user.
// If you decide to return this you should take great care
// coming up with useful and ideally actionable messages
// in Norwegian.
EndUserMessage end_user_message = 4;
// Request attachment. Will only be sent to pre-approved actions.
// Mostly used for public services like Gjenbruksid.
NorwegianFodselsnummer norwegian_fodselsnummer = 5;
// Says something about why an action request was denied.
DeniedReason denied_reason = 6;
}
message Code {
// Url safe string identifying the code.
//
// Examples:
// * gjenbruksid
// * lånekortnummer
string id = 1;
// The actual code
string code = 2;
// ISO-8601
string expires_at = 3;
// Is the app required to verify a cached code? Or can it assume
// that it never expires before the expire date?
bool must_verify = 4;
// Optional text to be displayed above the code
string header_text = 5;
// Optional text to be displayed under the code
string footer_text = 6;
}
message ErrorDescription {
// Something like: unknown-user or db-connection-error
// Should be declared in the action manifest to allow
// admins to map error codes to human readable messages.
string code = 1;
// Technical error message.
// Will not be shown to the end user.
string debugMessage = 2;
// Some errors like timeouts might be resolved by the user
// trying again while others are more permanent. Set this to
// true if you think that a quick retry might work.
bool permanent = 3;
}
// Says something about why an action request was denied.
message DeniedReason {
// Something like: unknown-user
// Should be declared in the action manifest to allow
// admins to map error codes to human readable messages.
string code = 1;
string debugMessage = 2;
}
// Provides an option to send a message back to the
// person who executed the action. Keep it short.
message EndUserMessage {
// Human readable message for end user.
TextContent message = 1;
// Optional link (to website)
string link = 2;
// Optional link name. Will be ignored without a link.
// Single line and max 20 characters.
string linkName = 3;
}
message NorwegianFodselsnummer {
string number = 1;
}
}
message TextContent {
string message = 1;
ContentType contentType = 2;
enum ContentType {
PLAIN_TEXT = 0;
MARKDOWN = 1;
}
}
// Some things are equipped with sensors allowing us to observe state like
// locked, unlocked, open, close, offline, online etc. Implementing this can
// help administrators of Oslonøkkelen to configure alerts when things go
// offline, remain open too long etc.
message ThingState {
// ISO-8601
string last_update = 1;
oneof value {
// Whether the door/window is in an open position or not
// (not to be confused with locked).
Open open = 2;
// Whether the door/window is locked or not.
// (not to be confused with open).
Locked locked = 3;
// Used to indicate the healthiness of an action related to a thing.
//
// Example: The device responsible for unlocking (action) a door (thing)
// bas been offline for 30 minutes.
ActionHealth action_health = 5;
// Allows a few lines of technical system logs related to a thing to
// be communicated to Oslonøkkelen
DebugLog debug_log = 7;
}
reserved 4;
reserved 6;
// Used to communicate whether the door is in the open position.
enum Open {
OPEN = 0;
CLOSED = 1;
}
// Used to communicate whether the door is locked.
enum Locked {
LOCKED = 0;
UNLOCKED = 1;
}
// A single door can be equipped with multiple devices that
// can fail separately. A door can have a working door pump action
// at the same time the device responsible for unlocking it is broken.
message ActionHealth {
// Must match the id of one of the actions of the thing
string action_id = 1;
// True if everything seems to be working
bool healthy = 2;
// Debug message to help administrators debug the problem.
// Will never be presented to end users.
string debug_message = 3;
}
// Used to communicate a few lines of technical logs to Oslonøkkelen.
message DebugLog {
repeated Line lines = 1;
message Line {
int64 timestamp_epoch_millis = 1;
Level level = 2;
string message = 3;
}
enum Level {
DEBUG = 0;
INFO = 1;
WARNING = 2;
ERROR = 3;
}
}
}