Skip to content

planet-nine-app/pref

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pref

Pref (short for preferences) utilizes the Sessionless protocol to provide developers with a place to store user preferences. It defaults to preferences which are scoped to a context via a supplied hash. This hash allows developers to scope preferenes to clients within their ecosystems.

What's novel about Pref is that preferences can be scoped globally, and made available to all apps that interact with Pref. This would allow a user to require biometrics before making a payment across multiple apps rather than having to set that in each app individually.

NOTE Globally accessible preferences must be flat String to String maps.

Overview

Pref is composed of a CRUD server and database pair, and companion client-side libraries. This repo defines the contract between client and server via REST API, provides database implementation(s) for storing the models used in that contract, and the methods necessary in a client implementation.

The typical usage will look something like:

sequenceDiagram
    Client->>+Server: Register User
    Server->>+DB: Save userUUID
    Server->>+Client: Sends userUUID
    Client->>+Server: Sends Preferences
    Server->>+DB: Saves Preferences
    Client->>+Server: Requests Preferences
    Server->>+DB: Checks Permission for Preferences
    Server->>+Client: Returns Preferences
Loading

And here's what the architecture looks like:

flowchart TD
    A[(DB)] <-->|CRUD| B{Server}
    B <--> |REST API| C[SDK in Language 1]
    B <-->|REST API| D[SDK in Language 2]
    B <-->|REST API| E[SDK in Language 3]
Loading

API

It doesn't get much CRUDier than this API:

POST /user/create Creates a new user if pubKey does not exist, and returns existing uuid if it does. signature message is: timestamp + pubKey + hash
Parameters
name required data type description
pubKey true string (hex) the publicKey of the user's keypair
timestamp true string in a production system timestamps prevent replay attacks
hash true string the state hash to save for the user
signature true string (signature) the signature from sessionless for the message
Responses
http code content-type response
200 application/json {"userUUID": <uuid>}
400 application/json {"code":"400","message":"Bad Request"}
Example cURL
 curl -X PUT -H "Content-Type: application/json" -d '{"pubKey": "key", "timestamp": "now", "signature": "sig"}' https://pref.planetnine.app/user/create
PUT /user/:uuid/preferences Puts a user's preferences signature message is: timestamp + userUUID + hash
Parameters
name required data type description
timestamp true string in a production system timestamps prevent replay attacks
userUUID true string the user's uuid
hash true string the old hash to replace
preferences true object the preferences to save
signature true string (signature) the signature from sessionless for the message
Responses
http code content-type response
200 application/json <preferences>
400 application/json {"code":"400","message":"Bad Request"}
Example cURL
 curl -X POST -H "Content-Type: application/json" -d '{"timestamp": "right now", "userUUID": "uuid", "hash": "hash", "preferences": {"foo": "bar"}, "signature": "signature"}' https://pref.planetnine.app/user/update-hash
GET /user/:uuid/preferences?timestamp=&hash=&signature= Gets a user's preferences.
Parameters
name required data type description
timestamp true string in a production system timestamps prevent replay attacks
hash true string the state hash saved client side
signature true string (signature) the signature from sessionless for the message
Responses
http code content-type response
200 application/json {"userUUID": <uuid>}
406 application/json {"code":"406","message":"Not acceptable"}
Example cURL
 curl -X GET -H "Content-Type: application/json" https://www.continuebee.com/<uuid>?timestamp=123&hash=hash&signature=signature 
PUT /user/:uuid/global/preferences Puts a user's globally available preferences signature message is: timestamp + userUUID + hash
Parameters
name required data type description
timestamp true string in a production system timestamps prevent replay attacks
userUUID true string the user's uuid
hash true string the old hash to replace
preferences true object the preferences to save
signature true string (signature) the signature from sessionless for the message
Responses
http code content-type response
200 application/json <preferences>
400 application/json {"code":"400","message":"Bad Request"}
Example cURL
 curl -X POST -H "Content-Type: application/json" -d '{"timestamp": "right now", "userUUID": "uuid", "hash": "hash", "preferences": {"foo": "bar"}, "signature": "signature"}' https://pref.planetnine.app/user/:uuid/global/preferences
GET /user/:uuid/preferences?timestamp=&hash=&signature= Gets a user's globally available preferences.
Parameters
name required data type description
timestamp true string in a production system timestamps prevent replay attacks
hash true string the state hash saved client side
signature true string (signature) the signature from sessionless for the message
Responses
http code content-type response
200 application/json {"userUUID": <uuid>}
406 application/json {"code":"406","message":"Not acceptable"}
Example cURL
 curl -X GET -H "Content-Type: application/json" https://pref.planetnine.app/user/:uuid/global/preferences?timestamp=123&hash=hash&signature=signature 
DELETE /user/delete Deletes a uuid and pubKey. signature message is: timestamp + userUUID + hash
Parameters
name required data type description
timestamp true string in a production system timestamps prevent replay attacks
userUUID true string the user's uuid
hash true string the old hash to replace
signature true string (signature) the signature from sessionless for the message
Responses
http code content-type response
202 application/json empty
400 application/json {"code":"400","message":"Bad Request"}
Example cURL
 curl -X DELETE https://pref.planetnine.app/user/delete

Databases

One of the biggest benefits of Sessionless is that it doesn't need to store any sensitive data. This means all of the data Pref cares about can all be saved in a single table/collection/whatever-other-construct-some-database-may-have. And that table looks like:

uuid pubKey hash
string string string

uuid, and pubKey should have unique constraints (Sessionless generated keys and uuids should not collide, but since this is a public API people may just reuse keys and uuids).

Client SDKs

Client SDKs need to generate keys via Sessionless, and implement the networking to interface with the server. To do so they should implement the following methods:

createUser(hash, newPreferences, saveKeys, getKeys) - Should generate keys, save them appropriately client side, and PUT to /user/create.

updatePreferences(uuid, hash, newPreferences) - Should PUT the passed in preferences.

saveGlobalPreferences(uuid, hash, newPreferences) - Should PUT the passed in global preferences.

getPreferences(uuid, hash) - Should GET preferences.

getGlobalPreferences(uuid, hash) - Should GET global preferences.

deleteUser(uuid, hash) - Should DELETE a user by calling /user/:uuid.

Use cases

NOTE Pref is experimental, and the instance at planetnine.app is ephemeral, and may go away or reset at any time. If you're making the next Palworld and want to use Pref, you're advised to self-host it, or contact zach@planetnine.app to help him upgrade the micro instance it runs on :).

  • Would probably take less time to list apps that don't have a notion of preferences... I can't think of any.

Self-hosting

This is a bit dependent on what the server implementations are, so we'll fill the details in later, but the idea is that continuebee is hostable by others either for public use like the main instance, or private use.

Contributing

To add to this repo, feel free to make a pull request.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published