prolog-vc-tools
    Preparing search index...

    prolog-vc-tools

    Prolog VC Tools

    This library provides a set of tools for converting Verifiable Credentials (VCs) into Prolog facts and rules. This allows for expressive and powerful policy-based access control and other logic-based systems to be built on top of a verifiable data model.

    Docs

    The library takes a VC as input, validates it against the corresponding schema, and then converts it into a Prolog fact or rule. These facts and rules can then be asserted into a Prolog engine to build a knowledge base.

    Here is the schema for a VC's credentialSubject for a person:

    {
    "title": "Person",
    "type": "object",
    "properties": {
    "claimType": {
    "type": "string",
    "const": "person"
    },
    "id": { "type": "string", "description": "Person's ID" },
    "updateView": {
    "type": "string",
    "enum": ["assert", "retract", "assertz", "asserta"],
    "default": "assert"
    }
    },
    "required": ["claimType", "id", "updateView"]
    }

    So following that schema we can construct this VC:

    {
    "credentialSubject": {
    "claimType": "person",
    "id": "person1",
    "updateView": "assert"
    }
    }

    And pass to the extractPrologStatement function which will return the following Prolog fact:

    assert(person(person1)).
    

    Here is the schema for a VC's credentialSubject for a rule.

    {
    "title": "Rule Definition (Generalized Boolean Logic)",
    "type": "object",
    "properties": {
    "claimType": {
    "type": "string",
    "const": "rule"
    },
    "name": { "type": "string" },
    "evaluate": { "$ref": "#/$defs/logicNode" },
    "variables": {
    "type": "array",
    "items": { "type": "string" }
    },
    "returns": { "enum": ["boolean"] },
    "updateView": {
    "type": "string",
    "enum": ["assert", "retract"],
    "default": "assert"
    }
    },
    "required": [
    "claimType",
    "name",
    "evaluate",
    "variables",
    "returns",
    "updateView"
    ],

    "$defs": {
    "logicNode": {
    "description": "A logical expression node (predicate or combinator)",
    "type": "object",
    "oneOf": [
    {
    "description": "A predicate (atomic condition)",
    "properties": {
    "predicate": { "type": "string" },
    "args": {
    "type": "array",
    "items": { "type": "string" }
    }
    },
    "required": ["predicate", "args"],
    "additionalProperties": false
    },
    {
    "description": "Logical AND combinator",
    "properties": {
    "and": {
    "type": "array",
    "items": { "$ref": "#/$defs/logicNode" },
    "minItems": 1
    }
    },
    "required": ["and"],
    "additionalProperties": false
    },
    {
    "description": "Logical OR combinator",
    "properties": {
    "or": {
    "type": "array",
    "items": { "$ref": "#/$defs/logicNode" },
    "minItems": 1
    }
    },
    "required": ["or"],
    "additionalProperties": false
    },
    {
    "description": "Logical NOT combinator",
    "properties": {
    "not": { "$ref": "#/$defs/logicNode" }
    },
    "required": ["not"],
    "additionalProperties": false
    }
    ]
    }
    }
    }

    Which is a bit complicated but lets us chain and embed multiple rules with ANDs, ORs and NOTs.

    So following that schema we can construct this VC:

    {
    "credentialSubject": {
    "claimType": "rule",
    "name": "my_rule",
    "evaluate": {
    "and": [
    { "predicate": "p", "args": ["a"] },
    { "predicate": "q", "args": ["b"] }
    ]
    },
    "variables": ["X"],
    "returns": "boolean",
    "updateView": "assert"
    }
    }

    And pass to the extractPrologStatement function which will return the following Prolog fact:

    assert(my_rule(X) :- (p(a), q(b))).
    

    The library is built around a set of schemas that define the structure of the VCs. These schemas represent the core concepts of a system that could be built using this library. Below are the categories of statements that get constructed using the VCs that implement the corresponding schema.

    • Person: Represents a user in the system.
    assert(person(personId)).
    
    • Person Custom Property: Allows for adding arbitrary properties to a person.
    assert(person_custom_property(person1, age, 30)).
    
    • Group: Represents a collection of people.
    assert(group(exampleGroupId)).
    
    • Group Custom Property: Allows for adding arbitrary properties to a group.
    assert(group_custom_property(group1, department, engineering)).
    
    • Entity Represents a more abstract entity.
    assert(entity(entityId)).
    
    • Entity Custom Property: Allows for adding arbitrary properties to an entity.
    assert(entity_custom_property(entityId, property, value)).
    
    • Entity Group: Reresents a collection of entities.
    assert(entity_group(entityGroupId)).
    
    • Entity Group Custom Property: Allows for adding arbitrary properties to an entity group.
    assert(entity_group_custom_property(entity_group_id, property, value)).
    

    These are pre-defined rules that provide relations between our existing entities.

    • Person Belongs to Group: A relationship that links a person to a group.
    assert(person_belongs_to_group(person1, group1))."
    
    • Resource Owned By Person: A relationship that indicates a person owns a resource.
    assert(resource_owned_by_person(resource1, person1)).
    
    • Resource Shared With Person: A relationship that indicates a resource is shared with a person.
    assert(resource_shared_with_person(sharer1, resource1, person1)).
    
    • Resource Shared With Group: A relationship that indicates a resource is shared with a group.
    assert(resource_shared_with_group(sharer1, resource1, group1)).
    
    • Resource Contained In: A relationship that links a resource to a folder.
    assert(resource_contained_in(resource1, folder1)).
    
    • Custom Relation: A relationship that links a resource to a folder.
    assert(trust(person, resource)).
    
    • Entity Belongs to Entity Group
    assert(entity_belongs_to_entity_group(entityID, entityGroupID)).
    
    • Resource: A generic entity that can be accessed.
    assert(resource(resource1)).
    
    • File: A specific type of resource.
    assert(file(resource1)).
    
    • Folder: A container for other resources.
    assert(folder(resource1)).
    
    • Rule: Defines a custom rule using a JSON-based logic structure. Supports conjunction, disjunction and negation of other rules.
    assert(my_rule(X) :- (p(a), q(b))).
    
    • Rule Custom: Defines a custom rule using raw Prolog.
    assert(my_rule(X) :- a(X), b(X)).
    
    • Query: Represents a query to the Prolog system.
    parent(john, mary).
    
    • Query Custom: Represents a custom query using raw Prolog.
    parent(john, X).
    

    The claimType property in the credential subject of a VC is used to determine which schema to validate against and how to generate the Prolog statement. The possible values for claimType are defined by the ClaimType enum:

    Claim Type Description
    person Represents a user in the system.
    person_custom_property A custom property for a person.
    Claim Type Description
    group Represents a group of people.
    group_custom_property A custom property for a group.
    Claim Type Description
    entity Represents a entity in the system.
    entity_custom_property A custom property for an entity.
    Claim Type Description
    person_belongs_to_group Links a person to a group.
    resource_owned_by_person Indicates a person owns a resource.
    resource_shared_with_group Indicates a resource is shared with a group.
    resource_shared_with_person Indicates a resource is shared with a person.
    resource_contained_in Links a resource to a folder.
    entity_belongs_to_entity_group Links an entity to an entity group.
    relation_custom A custom relationship.
    Claim Type Description
    resource A generic entity that can be accessed.
    file Labels a resource as a file.
    folder Labels a resource as a folder.
    Claim Type Description
    rule Defines a custom rule using a JSON-based logic structure.
    rule_custom Defines a custom rule using raw Prolog.
    Claim Type Description
    query Represents a query to the Prolog system.
    query_custom A custom query using raw Prolog.

    In a Node.js project, run npm i prolog-vc-tools.

    The primary function of this library is extractPrologStatement, which takes a VC that conforms to a supported schema and returns a Prolog statement.

    import { extractPrologStatement } from "prolog-vc-tools";

    const vc = {
    credentialSubject: {
    claimType: "person",
    id: "person1",
    updateView: "assert",
    },
    };

    const { fact, type } = extractPrologStatement(vc);

    console.log(fact); // assert(person(person1)).

    You can also pass an updateView argument which will override any updateView set in the credentialSubject.

    import { extractPrologStatement, UpdateView } from "prolog-vc-tools";

    const vc = {
    credentialSubject: {
    claimType: "person",
    id: "person1",
    updateView: "assert",
    },
    };

    const { fact, type } = extractPrologStatement(vc, UpdateView.Retract);

    console.log(fact); // retract(person(person1)).

    The library also provides a function isStringValidTerm to check if a string is a valid Prolog term.

    import { isStringValidTerm } from "prolog-vc-tools";

    const isValid = await isStringValidTerm("person(person1).");

    console.log(isValid); // true

    An application with multiple example implementations of systems using this library can be found here: policy-use-cases.

    A demo application that implements this library can be found here: prolog-vc-tools-app.

    Full schemas can be found here: GitHub.

    Example VCs implementing those schemas can be found here: Github.