Part 4: Party assignment automation
Thread: API
Learn how to use rulesets to automatically define party attributes for parties with fixed identities.
Prerequisites
- Have completed Part 1: Introduction to Parties
- Have completed Part 3: Party Assignment
- Understand JWT tokens and entity-to-party mapping
- Familiarity with YAML configuration
Learning outcomes
After completing this part, you'll be able to:
- Understand how rulesets automate party attribute assignment
- Define parties with fixed email addresses using rulesets
- Simplify instance creation by removing redundant party specifications
The party definition problem
In Part 3, we manually specified party attributes when creating instances:
{
"@parties": {
"editor": {
"claims": {
"email": ["alice@example.com"]
}
},
"approver": {
"claims": {
"email": ["bob@example.com"]
}
}
},
"content": "Q4 Financial Report"
}
This works well when parties vary per instance. But what if a party should automatically be the person who creates the instance? For example:
- The compliance party should always have the
{ "email": ["support@example.com"] }claim - The requester should automatically be set to the person making the request
Specifying these repeatedly is redundant—the information is already in the JWT token. Party assignment automation using rulesets solves this problem by automatically extracting claims from the JWT token, requiring values to match JWT claims, or setting values for all instances.
Importantly, the automation can also be used to comply with key requirements (compliance, security, soundness of business logic), e.g. by preventing API users from creating instances and binding claims they do not carry in their JWT to specific protocol parties (thereby opening uncontrolled access or creating illegitimate contractual obligations, for instance). As a consequence, using party assignment automation can be an integral part of secure application design. In any case, controlling party bindings at protocol instantiations needs to be part of sound applications design.
Understanding rulesets
A ruleset is a YAML configuration that defines how party claims should be automatically assigned. It allows you to:
- Set fixed attribute values for specific parties
- Enforce that certain parties always have specific emails
- Reduce the need to specify party attributes in API calls to create protocol instances
Example ruleset
demo.SupportRequest:
support:
set:
claims:
iss:
- https://example.com
email:
- support@example.com
requester:
extract:
claims:
- iss
- email
This ruleset says: "For all SupportRequest protocol instances in the demo package, the support party will set the
iss and email claims to ["https://example.com"] and ["support@example.com]."
When the protocol should only be created by one entity, the require keyword can ensure that the claims in the JWT
token match a specific one. For example, the SupportResolution protocol can be instantiated only by someone carrying
the support@example.com email claim in their JWT.
demo.SupportResolution:
support:
require:
claims:
iss:
- https://example.com
email:
- support@example.com
Practical example: Support request protocol
Let's model a support request system where:
- The requester is whoever makes the request (varies per instance)
- The support party is automatically set to
support@example.com
Step 1: Define the protocol
protocol[requester, support] SupportRequest(
var description: Text
) {
initial state open
state inProgress
final state resolved
final state closed
@api
permission[requester] addDetails(additionalInfo: Text) | open, inProgress {
description = description + "\n" + additionalInfo;
}
@api
permission[support] startWork() | open {
become inProgress;
}
@api
permission[support] resolve() | inProgress {
become resolved;
}
@api
permission[requester] close() | resolved {
become closed;
}
}
Step 2: Configure the ruleset
Create a ruleset file (e.g., rules.yml):
demo.SupportRequest:
support:
set:
claims:
iss:
- https://example.com
email:
- support@example.com
requester:
extract:
claims:
- iss
- email
This ruleset automatically extracts the iss and email claims from the JWT token and assigns them to the requester
party. It also assigns the { "email": ["support@example.com"] } claim to the support party for all instances.
Step 3: Create a support request (simplified)
With the ruleset in place, Alice creates a support request:
API Call:
POST /npl/support/SupportRequest
Authorization: Bearer <ALICE_JWT_TOKEN>
Content-Type: application/json
Request Body:
{
"@parties": {},
"description": "Unable to access document approval feature"
}
What's happening:
- Alice does not need to specify any party as both parties have a party automation rule
- The ruleset automatically extracts the
emailclaim from Alice's JWT token and assigns it to therequesterparty - The
supportparty is automatically set to the support email
Response:
{
"@id": "support-req-789",
"@state": "open",
"@parties": {
"requester": {
"claims": {
"email": ["alice@example.com"]
}
},
"support": {
"claims": {
"email": ["support@example.com"]
}
}
}
}
Notice the requester party is automatically populated with Alice's issuer and email from the JWT token and the
support party with the support issuer and email.
Step 4: Support team member starts work
Bob is a member of the support team and has support@example.com in his JWT token. He can start work on Alice's
request:
API Call:
POST /npl/document/SupportRequest/support-req-789/startWork
Authorization: Bearer <BOB_JWT_TOKEN>
Content-Type: application/json
Request Body: no body
What's happening:
- Bob's JWT token contains the claim
"email": "support@example.com" - The system checks if the
supportparty can be represented by Bob's entity—it can - Bob can call the
startWorkpermission
Response:
{}
Step 5: Support resolves the issue
API Call:
POST /npl/document/SupportRequest/support-req-789/resolve
Authorization: Bearer <BOB_JWT_TOKEN>
Content-Type: application/json
Request Body: no body
Response:
{}
Step 6: Alice closes the request
API Call:
POST /npl/document/SupportRequest/support-req-789/close
Authorization: Bearer <ALICE_JWT_TOKEN>
Content-Type: application/json
Request Body: no body
Response:
{}
How ruleset automation works
When you create a protocol instance with a ruleset:
- Ruleset with
extract: The system extracts claims from the JWT token of the user creating the instance - Ruleset with
set: The system assigns fixed claim values to parties - Ruleset with
require: The system requires specific claims to be present - Validation: The system ensures all required parties are defined, from the ruleset or from the party parameters in the API call payload
- Instance creation: The instance is created with complete party assignments
Flow diagram
API Request → JWT Token → Ruleset Applied → Complete Party Set → Instance Created
| | | | |
@parties: {} email claim extract claims All parties @id +
extracted + set claims defined @parties
Benefits of ruleset automation
Benefits of the ruleset include:
- Reduced redundancy when setting constant party claims
- Centralized claim setting in one place
- Automated use of JWT token to define party claims (convenience and security)
- Simplified client code
// Before: Must specify both parties
function createSupportRequest(description) {
return fetch('/npl/support/SupportRequest', {
method: 'POST',
body: JSON.stringify({
"@parties": {
"requester": {
"claims": { "email": ["alice@example.com"] }
},
"support": {
"claims": { "email": ["support@example.com"] }
}
},
"description": description
})
});
}
// After: Ruleset handles it automatically
function createSupportRequest(description) {
return fetch('/npl/support/SupportRequest', {
method: 'POST',
body: JSON.stringify({
"@parties": {}, // Both parties handled by ruleset
"description": description
})
});
}
What's next?
In the next part, you'll learn about entities belonging to others, which models ownership and hierarchical relationships in NPL.