Scopes API
Scope helpers work with any object that has a scopes: string[] property.
This includes DelegationResult from both verifyDelegation and verifyPresentation.
hasScope
Checks if a result contains a specific scope.
function hasScope(result: { scopes: string[] }, scope: string): booleanExample
import { hasScope } from "@credat/sdk";
if (hasScope(result, "email:read")) {
// Agent has email:read permission
}hasAnyScope
Checks if a result contains at least one of the given scopes.
function hasAnyScope(result: { scopes: string[] }, scopes: string[]): booleanExample
import { hasAnyScope } from "@credat/sdk";
if (hasAnyScope(result, ["files:read", "files:write"])) {
// Agent has at least one file permission
}hasAllScopes
Checks if a result contains all of the given scopes.
function hasAllScopes(result: { scopes: string[] }, scopes: string[]): booleanExample
import { hasAllScopes } from "@credat/sdk";
if (hasAllScopes(result, ["email:read", "email:send"])) {
// Agent has complete email access
}getAllScopes
Returns a copy of the scopes array.
function getAllScopes(result: { scopes: string[] }): string[]Example
import { getAllScopes } from "@credat/sdk";
const scopes = getAllScopes(result);
// ["email:read", "email:send", "calendar:write"]validateConstraints
Validates delegation constraints against a request context. Returns an array of violations --- empty if all constraints pass.
function validateConstraints(
constraints: DelegationConstraints | undefined,
context: ConstraintContext,
): ConstraintViolation[]Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
constraints | DelegationConstraints | undefined | Yes | Constraints from the verified delegation |
context | ConstraintContext | Yes | The current request context to validate against |
ConstraintContext
| Field | Type | Description |
|---|---|---|
transactionValue | number | undefined | The transaction value to check against maxTransactionValue |
domain | string | undefined | The target domain to check against allowedDomains |
rateLimit | number | undefined | Current rate count to check against rateLimit |
[key: string] | unknown | Custom context fields for custom constraints |
ConstraintViolation
| Field | Type | Description |
|---|---|---|
constraint | string | Name of the violated constraint |
message | string | Human-readable violation description |
Example
import { verifyDelegation, validateConstraints } from "@credat/sdk";
const result = await verifyDelegation(token, { ownerPublicKey });
if (result.valid) {
const violations = validateConstraints(result.constraints, {
transactionValue: 5000,
domain: "api.stripe.com",
});
if (violations.length > 0) {
console.error("Constraint violations:", violations);
// [{ constraint: "maxTransactionValue", message: "5000 exceeds max 1000" }]
}
}Notes
- Returns an empty array if
constraintsisundefined(no constraints = no violations) - Only checks built-in constraints (
maxTransactionValue,allowedDomains,rateLimit) against matching context fields - Skips checks where the context field is not provided (e.g., no
domainin context = skipallowedDomainscheck) - For custom constraints, use the manual approach
Usage pattern
A typical scope check in an API handler:
import { verifyPresentation, hasScope, hasAllScopes } from "@credat/sdk";
async function handleRequest(presentation, challenge) {
const result = await verifyPresentation(presentation, {
challenge,
ownerPublicKey,
agentPublicKey,
});
if (!result.valid) {
return { status: 401, error: "Unauthorized" };
}
// Route-level scope check
if (!hasScope(result, "api:read")) {
return { status: 403, error: "Missing api:read scope" };
}
// Operation-level scope check
if (operation === "delete" && !hasScope(result, "api:delete")) {
return { status: 403, error: "Missing api:delete scope" };
}
// Proceed
return { status: 200, data: "..." };
}Last updated on