LearnCard Documentation
GithubStatusSupportLaunch App
  • 🚀Introduction
    • What is LearnCard?
    • Use Cases & Possibilities
    • Ecosystem Architecture
  • ⚡Quick Start
    • Setup & Prerequisites
    • Your First Integration
  • 📚Tutorials
    • Create a Credential
    • Create a Boost
    • Create a ConsentFlow
    • Create a Connected Website
    • Send xAPI Statements
    • Listen to Webhooks
  • ✅How-To Guides
    • Verify My Issuer
    • Connect Systems
      • Connect a Website
      • Connect a Game
    • Implement Flows
      • Claim Data after Guardian Consent
      • Connect via CHAPI
        • ⭐CHAPI Wallet Setup Guide
        • ↔️Translating to CHAPI documentation
        • 🖥️Demo Application
        • 🔰Using LearnCard to Interact with a CHAPI Wallet
        • 📝Cheat Sheets
          • Issuers
          • Wallets
    • Deploy Infrastructure
      • Remote Key Management
      • Generate API Tokens
      • Signing Authority
      • Connect to Independent Network
      • Build a Plugin
  • 🛠️SDKs & API Reference
    • LearnCard Wallet SDK
      • Authentication
      • Usage Examples
      • SDK Reference
      • Plugin API Reference
      • Integration Strategies
      • Deployment
      • Troubleshooting
      • Changelog
    • LearnCloud Network API
      • Authentication
      • Usage Examples
      • Architecture
      • Notifications & Webhooks
      • Profiles
      • Profile Managers
      • Credentials
      • Boosts
      • Presentations
      • Storage
      • Contracts
      • DID Metadata
      • Claim Hooks
      • Auth Grants
      • Utilities
      • Models
      • OpenAPI
    • LearnCloud Storage API
      • Authentication
      • Usage Examples
      • Architecture
      • Storage
      • Index
      • User
      • Custom Storage
      • Utilities
      • Models
      • xAPI Reference
    • Plugins
      • Crypto
      • DIDKit
      • DID Key
      • Dynamic Loader
      • VC
        • Expiration Sub-Plugin
      • VC-Templates
      • VC-API
      • Ceramic
      • IDX
      • VPQR
      • Ethereum
      • CHAPI
      • LearnCard Network
      • LearnCloud
      • LearnCard
      • Simple Signing
      • Claimable Boosts
    • LearnCard CLI
  • 🧠Core Concepts
    • Identities & Keys
      • Decentralized Identifiers (DIDs)
      • Seed Phrases
      • Network Profiles
      • Signing Authorities
      • Trust Registries
    • Credentials & Data
      • Verifiable Credentials (VCs)
      • Credential Lifecycle
      • Schemas, Types, & Categories
      • Building Verifiable Credentials
      • Boost Credentials
      • Getting Started with Boosts
      • Credential URIs
      • xAPI Data
      • General Best Practices & Troubleshooting
    • Consent & Permissions
      • ConsentFlow Overview
      • Consent Contracts
      • User Consent & Terms
      • Consent Transactions
      • Auto-Boosts
      • Writing Consented Data
      • Accessing Consented Data
      • GameFlow Overview
    • Network & Interactions
      • Network Vision & Principles
      • Key Network Procedures
      • Core Interaction Workflows
    • Architecture & Principles
      • Control Planes
      • Plugin System
      • Auth Grants and API Tokens
  • 🔗Development
    • Contributing
Powered by GitBook
On this page
  • Control Planes:
  • ID Control Plane
  • id.did
  • id.keypair
  • Example plugins that implement the ID Plane
  • Read Control Plane
  • read.get
  • read.getMany
  • Example plugins that implement the Read Plane
  • Store Control Plane
  • store.upload
  • store.uploadEncrypted
  • store.uploadMany
  • Example plugins that implement the Store Plane
  • Index Control Plane
  • index.get
  • index.getPage
  • index.getCount
  • index.add
  • index.addMany
  • index.update
  • index.remove
  • index.removeAll
  • Example plugins that implement the Index Plane
  • Cache Control Plane
  • cache.getIndex
  • cache.setIndex
  • cache.getIndexPage
  • cache.setIndexPage
  • cache.getIndexCount
  • cache.setIndexCount
  • cache.flushIndex
  • cache.getVc
  • cache.setVc
  • cache.flushVc
  • Context Control Plane
  • context.resolveDocument
  • context.resolveStaticDocument [For Plugins]
  • context.resolveRemoteDocument [For Plugins]
  • Example Plugins that implement the Context Plane

Was this helpful?

  1. Core Concepts
  2. Architecture & Principles

Control Planes

PreviousArchitecture & PrinciplesNextPlugin System

Last updated 24 days ago

Was this helpful?

Control Planes are a primary way for consumers to interact with a LearnCard. A Control Plane provides an abstraction for a higher-order wallet object to initiate complex workflows while being agnostic to the means of accomplishing the workflow.

Control Planes:

  • Align plugins based on primary action categories: Identity, Signing, Verification, Storage, Caching, and Communication.

  • Specify interfaces for conforming plugins to implement.

  • Provide execution environments that support more complex workflows.

  • Allows for utilizing multiple plugins to support a particular request.

  • Streamline functionality for high-quality UX requirements, such as caching and querying capabilities.

  • Incentivizes plugin convergence, rather than divergence.

  • Enables plugin discovery, both internal and external.

For Example: when a user stores a credential, they may have a preference over where the credential is stored. Leveraging Controls Planes, a consumer of LearnCard may query for available storage options (IPFS, LocalStorage, DWN, Device Storage, etc.), ask the user which option they would like to use, and then initiate the storage workflow for the user's selection from a generic store function.

Each control plane serves a specific purpose:

Control Plane
Purpose
Key Methods

ID

Identity management

did, keypair

Read

Resolving URIs to credentials

get

Store

Storing credentials

upload, uploadEncrypted, uploadMany

Index

Managing credential references

get, add, update, remove

Cache

Caching for performance

getIndex, setIndex, getVc, setVc

Context

Managing contextual information

resolveDocument

A key feature of the control planes system is that when appropriate, a specific plugin implementing a plane can be chosen. For example, when storing a credential, you can specify which storage plugin to use:

// Store a credential using the Ceramic plugin
const uri = await learnCard.store.Ceramic.upload(credential);

// Store a credential using the default (first available) plugin
const uri = await learnCard.store.upload(credential);

To help better understand what Control Planes are, it may be easiest for you to take a look at the available Control Planes within LearnCard:

ID Control Plane

The ID Control Plane is the interface responsible for managing the holder's identity. This means storing/managing key material.

Plugins that implement this Control Plane will generally need to be instantiated in some way, and with some kind of input, such as a seed/existing key material, or by making a request to a third party that can provide key material.

The ID Plane implements two methods: did, and keypair

id.did

id.keypair

Example plugins that implement the ID Plane

Read Control Plane

The Read Plane implements one method: get

read.get

If a plugin implementing get is unable to resolve a URI, it should return undefined, allowing other plugins to take a crack at resolving that URI. If no plugins are able to resolve the URI, the LearnCard will return undefined.

read.getMany

Example plugins that implement the Read Plane

Store Control Plane

Note: In order to use this plane, you will have to choose where to store the Verifiable Credential!

You can get a list of available storage providers using the providers field:

console.log(learnCard.store.providers);
// {
//     Ceramic: {
//       name: 'Ceramic',
//       displayName: 'Ceramic',
//       description: 'Uploads/resolves credentials using the Ceramic Network (https://ceramic.network/)'
//     },
//     LearnCloud: {
//         name: 'LearnCloud',
//         displayName: 'LearnCloud',
//         description: 'LearnCloud Integration'
//     }
// }

The Store Plane implements three methods: upload, (optionally) uploadEncrypted, and (optionally) uploadMany

store.upload

store.uploadEncrypted

Note: This method is optional

The uploadEncrypted method allows you to encrypt a credential before uploading it, optionally specifying recipients who are allowed to decrypt the resolved credential. This is generally going to be safer, and it is heavily encouraged for Providers to implement this method!

store.uploadMany

Note: This method is optional

Example plugins that implement the Store Plane

Index Control Plane

Note: In order to use some of the methods of this plane, you will have to choose where to store the index!

You can get a list of available index providers using the providers field:

console.log(learnCard.index.providers);
// {
//     LearnCloud: {
//         name: 'LearnCloud',
//         displayName: 'LearnCloud',
//         description: 'LearnCloud Integration'
//     },
//     IDX: {
//       name: 'IDX',
//       displayName: 'IDX',
//       description: 'Stores a bespoke index of credentials for an individual based on their did'
//     }
// }

The Index Plane implements eight methods: get, (optionally) getPage, (optionally) getCount, add, addMany, update, remove, and removeAll.

index.get

Hint: You may use the "all" provider to combine the CredentialRecords of all providers with this method:

console.log(await learnCard.index.all.get());
// []

index.getPage

Note: This method is optional

When there are a lot of credentials stored in the index for a given query, it can be useful to paginate your queries rather than request all of them at once. That is what getPage is for! This call will return an object of the following shape:

type GetPageResult<Metadata extends Record<string, any>> = {
    cursor?: string;
    hasMore: boolean;
    records: CredentialRecord<Metadata>[];
};

Using the hasMore and cursor fields, you can determine if you should request the next page, as well as how to request the next page. The below example shows a simple way to request all available pages:

const records: CredentialRecord[] = [];

let result = await learnCard.index.LearnCloud.getPage();
records.push(result.records);

while (result.hasMore) {
    result = await learnCard.index.LearnCloud.getPage(undefined, { cursor: result.cursor });
    records.push(result.records);
}

index.getCount

Note: This method is optional

Sometimes, it can be useful for an app to display the total number of records for a given query without wanting to actual grab every credential for that query. This is where getCount comes in handy!

const totalRecords = await learnCard.index.LearnCloud.getCount();
const totalAchievementRecords = await learnCard.index.LearnCloud.getCount({ type: 'Achievement' });

index.add

The add method takes in a CredentialRecord and adds it to the holder's personal index.

index.addMany

The optional addMany method takes in an array of CredentialRecords and adds them to the holder's personal index.

index.update

The update method takes in an ID and an update object and updates a CredentialRecord in the holder's personal index.

index.remove

The remove method takes in an ID and removes the CredentialRecord with the corresponding ID from the holder's personal index.

index.removeAll

The optional removeAll method flushes all CredentialRecords from the holder's personal index.

Example plugins that implement the Index Plane

Cache Control Plane

The Cache Control Plane is responsible for speeding up and making a LearnCard more efficient through the use of Caching.

To better encourage and allow separation of the caching between different planes, Cache plugins are required to implement separate caching methods for each plane. In general, when consuming a LearnCard object, you should rarely, if ever, need to interact with the cache directly—it should just work underneath each of the other Planes 🚀!

The Cache Plane implements ten methods: getIndex, setIndex, getIndexPage, setIndexPage, (optionally) getIndexCount, (optionally) setIndexCount, flushIndex, getVc, setVc, and flushVc

cache.getIndex

The getIndex method takes in a query returns a list of CredentialRecords, similar to the Index Plane's get method.

cache.setIndex

The setIndex method takes in a query and a list of CredentialRecords and caches the records against the query, returning true if successful and false if not.

cache.getIndexPage

The getIndexPage method takes in a query with pagination options and returns a paginated result of CredentialRecords, similar to the Index Plane's getPage method.

cache.setIndexPage

The setIndexPage method takes in a query with pagination options and a paginated result of CredentialRecords and caches the result against the query/options, returning true if successful and false if not.

cache.getIndexCount

The getIndexCount method takes in a query and returns a number, intending to cache the Index Plane's getCount method.

cache.setIndexCount

The setIndexCount method takes in a query and number and caches the number against the query, returning true if successful and false if not.

cache.flushIndex

The flushIndex method empties out everything in the cache that can be returned by getIndex, getIndexPage, or getIndexCount

cache.getVc

The getVc method takes in a URI and returns a Verifiable Credential, similar to the Read Plane's get method.

cache.setVc

The setVc method takes in a URI and a Verifiable Credential and caches the Verifiable Credential against the URI, returning true if successful and false if not.

cache.flushVc

The flushVc method empties out everything in the cache that can be returned by getVc.

Context Control Plane

The Context Control Plane allows plugins to control how these JSON-LD contexts get resolved. Because it should be considered a security hole to resolve a context at runtime, plugins are expected to expose two different methods for static and dynamic resolution. On the final resulting LearnCard object, there is then only one method with an argument allowing for contexts to be resolved dynamically.

The Context Plane implements one method: resolveDocument

context.resolveDocument

The resolveDocument method takes in the URI to a JSON-LD Context and returns the full JSON-LD Context. By passing in true as the second argument, contexts may be resolved dynamically.

context.resolveStaticDocument [For Plugins]

When creating a Plugin that implements the Context Plane, you must implement the resolveStaticDocument method. This method simply does the same as the LearnCard-level resolveDocument method, but does not allow passing in a second argument to denote resolving dynamically.

context.resolveRemoteDocument [For Plugins]

When creating a Plugin that implements the Context Plane, you may implement the resolveRemoteDocument method. This method is identical to resolveStaticDocument, but by using this method, you are signifying that contexts will be loaded dynamically.

Security Considerations

Example Plugins that implement the Context Plane

The did method (optionally) takes in a , and returns a did.

The keypair method (optionally) takes in a cryptographic algorithm (e.g. ed25519, secp256k1, etc), and returns a .

The Read Control Plane is the interface responsible for resolving a to its Verifiable Credential.

If the LearnCard also implements the , then this Plane will automatically be cached!

The get method takes in a and resolves it to a Verifiable Credential.

The getMany method takes in an array of s and resolves them to an array of Verifiable Credentials.

The Store Control Plane is the interface responsible for storing a Verifiable Credential and returning a that resolves to it.

If the LearnCard also implements the , then this Plane will automatically be cached!

The upload method takes in a Verifiable Credential, stores the credential, and converts it into a resolvable .

The uploadMany method takes in an array of Verifiable Credentials, stores the credentials, and converts them into an array of resolvable .

The Index Control Plane is the interface responsible for managing operations on the holder's personal index.

If the LearnCard also implements the , then this method will automatically be cached!

The get method takes in a Mongo-style query and returns a list of CredentialRecords, which are primarily an ID, a , and some metadata.

If the LearnCard also implements the , then this method will automatically be cached!

If the LearnCard also implements the , then this Plane will automatically be cached!

When working with , such as with , you'll often need to resolve contexts. These contexts are themselves JSON-LD documents, being hosted at the URL embedded in the JSON-LD object. While it is easy enough to make a simple request to that URL and retrieve that document, there are many reasons why you might not want to do that every time. Most notably, for security and performance.

Resolving JSON-LD contexts dynamically comes with some serious security implications. Please read the following for more detail:

🧠
method
JWK
DID Key
URI
Cache Plane
URI
URI
Ceramic
LearnCloud
URI
Cache Plane
URI
URIs
Ceramic
LearnCloud
CRUD
Cache Plane
URI
Cache Plane
Cache Plane
IDX
LearnCloud
JSON-LD
Verifiable Credentials
https://www.w3.org/TR/json-ld11/#iana-security
DIDKit
Dynamic Loader
Diagram showing basic lifecycle of control plane interactions.