feat(codec): add json schemas for policy language and primitives
This commit is contained in:
305
internal/codec/policy.json
Normal file
305
internal/codec/policy.json
Normal file
@@ -0,0 +1,305 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://ucan.xyz/schemas/policy.json",
|
||||
"title": "UCAN Policy Language",
|
||||
"description": "Policy statements and selectors for constraining invocation arguments",
|
||||
"$defs": {
|
||||
"Selector": {
|
||||
"title": "Policy Selector",
|
||||
"description": "jq-inspired selector for navigating IPLD data structures",
|
||||
"type": "string",
|
||||
"pattern": "^\\.(([a-zA-Z_][a-zA-Z0-9_]*)|(\\[[^\\]]+\\])|(\\[\\])|(\\[-?\\d+\\])|(\\[\\d*:\\d*\\]))?((\\.[a-zA-Z_][a-zA-Z0-9_]*)|(\\[[^\\]]+\\])|(\\[\\])|(\\[-?\\d+\\])|(\\[\\d*:\\d*\\]))*\\??$",
|
||||
"examples": [
|
||||
".",
|
||||
".foo",
|
||||
".bar[0]",
|
||||
".items[-1]",
|
||||
".data[2:5]",
|
||||
".optional?"
|
||||
]
|
||||
},
|
||||
"GlobPattern": {
|
||||
"title": "Glob Pattern",
|
||||
"description": "Pattern for 'like' operator. * = wildcard, \\* = literal",
|
||||
"type": "string",
|
||||
"examples": [
|
||||
"*@example.com",
|
||||
"prefix*suffix"
|
||||
]
|
||||
},
|
||||
"EqualityOperator": {
|
||||
"title": "Equality Operator",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"==",
|
||||
"!="
|
||||
]
|
||||
},
|
||||
"InequalityOperator": {
|
||||
"title": "Inequality Operator",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
">",
|
||||
">=",
|
||||
"<",
|
||||
"<="
|
||||
]
|
||||
},
|
||||
"EqualityStatement": {
|
||||
"title": "Equality Statement",
|
||||
"description": "Deep comparison: [operator, selector, value]",
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{
|
||||
"$ref": "#/$defs/EqualityOperator"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/Selector"
|
||||
},
|
||||
{}
|
||||
],
|
||||
"minItems": 3,
|
||||
"maxItems": 3,
|
||||
"examples": [
|
||||
[
|
||||
"==",
|
||||
".status",
|
||||
"draft"
|
||||
],
|
||||
[
|
||||
"!=",
|
||||
".deleted",
|
||||
true
|
||||
]
|
||||
]
|
||||
},
|
||||
"InequalityStatement": {
|
||||
"title": "Inequality Statement",
|
||||
"description": "Numeric comparison: [operator, selector, number]",
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{
|
||||
"$ref": "#/$defs/InequalityOperator"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/Selector"
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
}
|
||||
],
|
||||
"minItems": 3,
|
||||
"maxItems": 3,
|
||||
"examples": [
|
||||
[
|
||||
">",
|
||||
".age",
|
||||
18
|
||||
],
|
||||
[
|
||||
"<=",
|
||||
".price",
|
||||
100.50
|
||||
]
|
||||
]
|
||||
},
|
||||
"LikeStatement": {
|
||||
"title": "Like Statement",
|
||||
"description": "Glob pattern matching: ['like', selector, pattern]",
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{
|
||||
"const": "like"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/Selector"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/GlobPattern"
|
||||
}
|
||||
],
|
||||
"minItems": 3,
|
||||
"maxItems": 3,
|
||||
"examples": [
|
||||
[
|
||||
"like",
|
||||
".email",
|
||||
"*@example.com"
|
||||
]
|
||||
]
|
||||
},
|
||||
"NotStatement": {
|
||||
"title": "Not Statement",
|
||||
"description": "Logical negation: ['not', statement]",
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{
|
||||
"const": "not"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/PolicyStatement"
|
||||
}
|
||||
],
|
||||
"minItems": 2,
|
||||
"maxItems": 2
|
||||
},
|
||||
"AndStatement": {
|
||||
"title": "And Statement",
|
||||
"description": "Logical AND: ['and', [statements...]]. Empty array = true",
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{
|
||||
"const": "and"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/PolicyStatement"
|
||||
}
|
||||
}
|
||||
],
|
||||
"minItems": 2,
|
||||
"maxItems": 2
|
||||
},
|
||||
"OrStatement": {
|
||||
"title": "Or Statement",
|
||||
"description": "Logical OR: ['or', [statements...]]. Empty array = true",
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{
|
||||
"const": "or"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/PolicyStatement"
|
||||
}
|
||||
}
|
||||
],
|
||||
"minItems": 2,
|
||||
"maxItems": 2
|
||||
},
|
||||
"AllStatement": {
|
||||
"title": "All Statement",
|
||||
"description": "Universal quantifier: ['all', selector, statement]",
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{
|
||||
"const": "all"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/Selector"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/PolicyStatement"
|
||||
}
|
||||
],
|
||||
"minItems": 3,
|
||||
"maxItems": 3,
|
||||
"examples": [
|
||||
[
|
||||
"all",
|
||||
".reviewers",
|
||||
[
|
||||
"like",
|
||||
".email",
|
||||
"*@example.com"
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"AnyStatement": {
|
||||
"title": "Any Statement",
|
||||
"description": "Existential quantifier: ['any', selector, statement]",
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{
|
||||
"const": "any"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/Selector"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/PolicyStatement"
|
||||
}
|
||||
],
|
||||
"minItems": 3,
|
||||
"maxItems": 3,
|
||||
"examples": [
|
||||
[
|
||||
"any",
|
||||
".tags",
|
||||
[
|
||||
"==",
|
||||
".",
|
||||
"urgent"
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"PolicyStatement": {
|
||||
"title": "Policy Statement",
|
||||
"description": "A single policy predicate expression",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/$defs/EqualityStatement"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/InequalityStatement"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/LikeStatement"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/NotStatement"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/AndStatement"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/OrStatement"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/AllStatement"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/AnyStatement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Policy": {
|
||||
"title": "UCAN Policy",
|
||||
"description": "Array of statements forming implicit AND. Constrains invocation args.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/PolicyStatement"
|
||||
},
|
||||
"examples": [
|
||||
[],
|
||||
[
|
||||
[
|
||||
"==",
|
||||
".from",
|
||||
"alice@example.com"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"==",
|
||||
".status",
|
||||
"draft"
|
||||
],
|
||||
[
|
||||
"all",
|
||||
".reviewer",
|
||||
[
|
||||
"like",
|
||||
".email",
|
||||
"*@example.com"
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
118
internal/codec/primitives.json
Normal file
118
internal/codec/primitives.json
Normal file
@@ -0,0 +1,118 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://ucan.xyz/schemas/primitives.json",
|
||||
"title": "UCAN Primitive Types",
|
||||
"description": "Core primitive types used across all UCAN specifications",
|
||||
"$defs": {
|
||||
"DID": {
|
||||
"title": "Decentralized Identifier",
|
||||
"description": "A W3C Decentralized Identifier (DID) string",
|
||||
"type": "string",
|
||||
"pattern": "^did:[a-z0-9]+:[a-zA-Z0-9._%-]+(:[a-zA-Z0-9._%-]+)*([/?#].*)?$",
|
||||
"examples": [
|
||||
"did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp",
|
||||
"did:web:example.com"
|
||||
]
|
||||
},
|
||||
"CID": {
|
||||
"title": "Content Identifier",
|
||||
"description": "IPLD CIDv1 with DAG-CBOR codec and SHA-256 multihash (base58btc)",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"/": {
|
||||
"type": "string",
|
||||
"pattern": "^zdpu[a-km-zA-HJ-NP-Z1-9]+$"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"/"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Bytes": {
|
||||
"title": "Binary Data",
|
||||
"description": "Binary data in DAG-JSON format (base64 encoded)",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"/": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bytes": {
|
||||
"type": "string",
|
||||
"contentEncoding": "base64"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"bytes"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"/"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Timestamp": {
|
||||
"title": "Unix Timestamp",
|
||||
"description": "Unix timestamp in seconds (53-bit integer for JS compatibility)",
|
||||
"type": "integer",
|
||||
"minimum": -9007199254740991,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"NullableTimestamp": {
|
||||
"title": "Nullable Timestamp",
|
||||
"description": "Timestamp or null for non-expiring tokens",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/$defs/Timestamp"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"VarsigHeader": {
|
||||
"title": "Varsig Header",
|
||||
"description": "Variable signature header with algorithm metadata",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/$defs/Bytes"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Signature": {
|
||||
"title": "Cryptographic Signature",
|
||||
"description": "Raw signature bytes",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/$defs/Bytes"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Command": {
|
||||
"title": "UCAN Command",
|
||||
"description": "Slash-delimited path describing an action (lowercase, starts with /)",
|
||||
"type": "string",
|
||||
"pattern": "^/([a-z0-9_\\u00C0-\\u024F]+(/[a-z0-9_\\u00C0-\\u024F]+)*)?$",
|
||||
"examples": [
|
||||
"/",
|
||||
"/crud/create",
|
||||
"/msg/send",
|
||||
"/ucan/revoke"
|
||||
]
|
||||
},
|
||||
"Metadata": {
|
||||
"title": "Metadata",
|
||||
"description": "Arbitrary metadata map",
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"Arguments": {
|
||||
"title": "Command Arguments",
|
||||
"description": "Map of command arguments",
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
}
|
||||
1160
internal/codec/ucan-schemas.json
Normal file
1160
internal/codec/ucan-schemas.json
Normal file
File diff suppressed because it is too large
Load Diff
592
src/ucan.ts
Normal file
592
src/ucan.ts
Normal file
@@ -0,0 +1,592 @@
|
||||
/**
|
||||
* UCAN Complete TypeScript Type Definitions
|
||||
* User-Controlled Authorization Network v1.0.0-rc.1
|
||||
*
|
||||
* Comprehensive types for Tokens, Delegation, and Invocation specifications
|
||||
*/
|
||||
|
||||
// =============================================================================
|
||||
// PRIMITIVES
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Decentralized Identifier (DID) string
|
||||
* @see https://www.w3.org/TR/did-core/
|
||||
*/
|
||||
export type DID = `did:${string}:${string}`;
|
||||
|
||||
/**
|
||||
* IPLD Content Identifier in DAG-JSON format
|
||||
* CIDv1 with DAG-CBOR codec and SHA-256 multihash, base58btc encoded
|
||||
*/
|
||||
export interface CID {
|
||||
"/": string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binary data in DAG-JSON format (base64 encoded)
|
||||
*/
|
||||
export interface Bytes {
|
||||
"/": {
|
||||
bytes: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Unix timestamp in seconds (53-bit integer for JS compatibility)
|
||||
* Range: -9007199254740991 to 9007199254740991
|
||||
*/
|
||||
export type Timestamp = number;
|
||||
|
||||
/**
|
||||
* Nullable timestamp - null indicates non-expiring
|
||||
*/
|
||||
export type NullableTimestamp = Timestamp | null;
|
||||
|
||||
/**
|
||||
* Varsig v1 header containing cryptographic algorithm metadata
|
||||
*/
|
||||
export type VarsigHeader = Bytes;
|
||||
|
||||
/**
|
||||
* Raw signature bytes
|
||||
*/
|
||||
export type Signature = Bytes;
|
||||
|
||||
// =============================================================================
|
||||
// COMMANDS
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* UCAN Command - slash-delimited path describing the action
|
||||
* Must be lowercase, start with '/', no trailing slash
|
||||
*/
|
||||
export type Command =
|
||||
| "/"
|
||||
| `/${string}`
|
||||
| `/crud/${CRUDAction}`
|
||||
| `/msg/${MessageAction}`
|
||||
| `/ucan/${UCANAction}`
|
||||
| `/wasm/${WasmAction}`;
|
||||
|
||||
export type CRUDAction = "create" | "read" | "update" | "delete" | "mutate";
|
||||
export type MessageAction = "send" | "receive";
|
||||
export type UCANAction = "revoke";
|
||||
export type WasmAction = "run";
|
||||
|
||||
// =============================================================================
|
||||
// POLICY LANGUAGE
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* jq-inspired selector for navigating IPLD data
|
||||
* @example "." | ".foo" | ".bar[0]" | ".items[-1]" | ".optional?"
|
||||
*/
|
||||
export type Selector = string;
|
||||
|
||||
/**
|
||||
* Glob pattern for 'like' operator
|
||||
* Use * for wildcard, \* for literal asterisk
|
||||
*/
|
||||
export type GlobPattern = string;
|
||||
|
||||
// Policy Operators
|
||||
export type EqualityOperator = "==" | "!=";
|
||||
export type InequalityOperator = ">" | ">=" | "<" | "<=";
|
||||
export type ConnectiveOperator = "and" | "or";
|
||||
export type QuantifierOperator = "all" | "any";
|
||||
|
||||
// Policy Statements
|
||||
export type EqualityStatement = [EqualityOperator, Selector, unknown];
|
||||
export type InequalityStatement = [InequalityOperator, Selector, number];
|
||||
export type LikeStatement = ["like", Selector, GlobPattern];
|
||||
export type NotStatement = ["not", PolicyStatement];
|
||||
export type AndStatement = ["and", PolicyStatement[]];
|
||||
export type OrStatement = ["or", PolicyStatement[]];
|
||||
export type AllStatement = ["all", Selector, PolicyStatement];
|
||||
export type AnyStatement = ["any", Selector, PolicyStatement];
|
||||
|
||||
/**
|
||||
* Union of all policy statement types
|
||||
*/
|
||||
export type PolicyStatement =
|
||||
| EqualityStatement
|
||||
| InequalityStatement
|
||||
| LikeStatement
|
||||
| NotStatement
|
||||
| AndStatement
|
||||
| OrStatement
|
||||
| AllStatement
|
||||
| AnyStatement;
|
||||
|
||||
/**
|
||||
* UCAN Policy - array of statements forming implicit AND
|
||||
*/
|
||||
export type Policy = PolicyStatement[];
|
||||
|
||||
// =============================================================================
|
||||
// METADATA & ARGUMENTS
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Arbitrary metadata map
|
||||
*/
|
||||
export type Metadata = Record<string, unknown>;
|
||||
|
||||
/**
|
||||
* Command arguments - shape defined by command type
|
||||
*/
|
||||
export type Arguments = Record<string, unknown>;
|
||||
|
||||
// =============================================================================
|
||||
// CAPABILITY
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* UCAN Capability - the semantically-relevant claim of a delegation
|
||||
*/
|
||||
export interface Capability {
|
||||
/** Subject DID or null for powerline delegation */
|
||||
sub: DID | null;
|
||||
/** Command being delegated */
|
||||
cmd: Command;
|
||||
/** Policy constraints on invocation arguments */
|
||||
pol: Policy;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// DELEGATION
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* UCAN Delegation Payload (ucan/dlg@1.0.0-rc.1)
|
||||
*/
|
||||
export interface DelegationPayload {
|
||||
/** Issuer DID - the delegator */
|
||||
iss: DID;
|
||||
/** Audience DID - the delegate */
|
||||
aud: DID;
|
||||
/** Subject DID or null for powerline */
|
||||
sub: DID | null;
|
||||
/** Command being delegated */
|
||||
cmd: Command;
|
||||
/** Policy constraints */
|
||||
pol: Policy;
|
||||
/** Random nonce for unique CID */
|
||||
nonce: Bytes;
|
||||
/** Optional metadata */
|
||||
meta?: Metadata;
|
||||
/** Not-before timestamp (optional) */
|
||||
nbf?: Timestamp;
|
||||
/** Expiration timestamp or null */
|
||||
exp: NullableTimestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegation signature payload structure
|
||||
*/
|
||||
export interface DelegationSigPayload {
|
||||
/** Varsig header */
|
||||
h: VarsigHeader;
|
||||
/** Delegation payload with version tag */
|
||||
"ucan/dlg@1.0.0-rc.1": DelegationPayload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete UCAN Delegation envelope
|
||||
*/
|
||||
export type Delegation = [Signature, DelegationSigPayload];
|
||||
|
||||
// =============================================================================
|
||||
// INVOCATION
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Proof chain - ordered CIDs of delegations from Subject to Invoker
|
||||
*/
|
||||
export type ProofChain = CID[];
|
||||
|
||||
/**
|
||||
* UCAN Invocation Payload (ucan/inv@1.0.0-rc.1)
|
||||
*/
|
||||
export interface InvocationPayload {
|
||||
/** Issuer DID - the invoker */
|
||||
iss: DID;
|
||||
/** Subject DID being invoked */
|
||||
sub: DID;
|
||||
/** Optional audience DID if executor differs from subject */
|
||||
aud?: DID;
|
||||
/** Command to execute */
|
||||
cmd: Command;
|
||||
/** Command arguments */
|
||||
args: Arguments;
|
||||
/** Proof chain of delegations */
|
||||
prf: ProofChain;
|
||||
/** Optional metadata */
|
||||
meta?: Metadata;
|
||||
/** Optional nonce for non-idempotent invocations */
|
||||
nonce?: Bytes;
|
||||
/** Expiration timestamp */
|
||||
exp: NullableTimestamp;
|
||||
/** Optional issuance timestamp */
|
||||
iat?: Timestamp;
|
||||
/** Optional CID of Receipt that enqueued this task */
|
||||
cause?: CID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invocation signature payload structure
|
||||
*/
|
||||
export interface InvocationSigPayload {
|
||||
/** Varsig header */
|
||||
h: VarsigHeader;
|
||||
/** Invocation payload with version tag */
|
||||
"ucan/inv@1.0.0-rc.1": InvocationPayload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete UCAN Invocation envelope
|
||||
*/
|
||||
export type Invocation = [Signature, InvocationSigPayload];
|
||||
|
||||
// =============================================================================
|
||||
// TASK
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* UCAN Task - subset of Invocation fields uniquely determining work
|
||||
* Task ID is the CID of these fields
|
||||
*/
|
||||
export interface Task {
|
||||
/** Subject DID */
|
||||
sub: DID;
|
||||
/** Command to execute */
|
||||
cmd: Command;
|
||||
/** Command arguments */
|
||||
args: Arguments;
|
||||
/** Nonce for uniqueness */
|
||||
nonce: Bytes;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// RECEIPT
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Successful execution result
|
||||
*/
|
||||
export interface SuccessResult<T = unknown> {
|
||||
ok: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Failed execution result
|
||||
*/
|
||||
export interface ErrorResult<E = unknown> {
|
||||
err: E;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execution outcome
|
||||
*/
|
||||
export type ExecutionResult<T = unknown, E = unknown> = SuccessResult<T> | ErrorResult<E>;
|
||||
|
||||
/**
|
||||
* UCAN Receipt Payload - execution result
|
||||
*/
|
||||
export interface ReceiptPayload<T = unknown, E = unknown> {
|
||||
/** Executor DID */
|
||||
iss: DID;
|
||||
/** CID of executed Invocation */
|
||||
ran: CID;
|
||||
/** Execution result */
|
||||
out: ExecutionResult<T, E>;
|
||||
/** Effects - CIDs of Tasks to enqueue */
|
||||
fx?: CID[];
|
||||
/** Optional metadata */
|
||||
meta?: Metadata;
|
||||
/** Issuance timestamp */
|
||||
iat?: Timestamp;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// REVOCATION
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Revocation arguments
|
||||
*/
|
||||
export interface RevocationArgs {
|
||||
/** CID of delegation to revoke */
|
||||
ucan: CID;
|
||||
}
|
||||
|
||||
/**
|
||||
* UCAN Revocation Payload
|
||||
*/
|
||||
export interface RevocationPayload {
|
||||
/** Revoker DID - must be issuer in delegation chain */
|
||||
iss: DID;
|
||||
/** Subject of delegation being revoked */
|
||||
sub: DID;
|
||||
/** Revocation command */
|
||||
cmd: "/ucan/revoke";
|
||||
/** Revocation arguments */
|
||||
args: RevocationArgs;
|
||||
/** Proof chain */
|
||||
prf: ProofChain;
|
||||
/** Nonce */
|
||||
nonce: Bytes;
|
||||
/** Expiration */
|
||||
exp: NullableTimestamp;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// ENVELOPE
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Generic UCAN Envelope format
|
||||
*/
|
||||
export type UCANEnvelope<P extends object> = [
|
||||
Signature,
|
||||
{
|
||||
h: VarsigHeader;
|
||||
} & P
|
||||
];
|
||||
|
||||
// =============================================================================
|
||||
// CRYPTOGRAPHY
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Supported signature algorithms
|
||||
*/
|
||||
export type CryptoAlgorithm = "Ed25519" | "P-256" | "secp256k1";
|
||||
|
||||
/**
|
||||
* Supported hash algorithms
|
||||
*/
|
||||
export type HashAlgorithm = "sha2-256";
|
||||
|
||||
// =============================================================================
|
||||
// VALIDATION
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Validation error codes
|
||||
*/
|
||||
export type ValidationErrorCode =
|
||||
| "EXPIRED"
|
||||
| "NOT_YET_VALID"
|
||||
| "INVALID_SIGNATURE"
|
||||
| "PRINCIPAL_MISALIGNMENT"
|
||||
| "POLICY_VIOLATION"
|
||||
| "REVOKED"
|
||||
| "INVALID_PROOF_CHAIN"
|
||||
| "UNKNOWN_COMMAND"
|
||||
| "MALFORMED_TOKEN";
|
||||
|
||||
/**
|
||||
* Validation error structure
|
||||
*/
|
||||
export interface ValidationError {
|
||||
code: ValidationErrorCode;
|
||||
message: string;
|
||||
details?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Successful validation result
|
||||
*/
|
||||
export interface ValidationSuccess {
|
||||
valid: true;
|
||||
capability: Capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* Failed validation result
|
||||
*/
|
||||
export interface ValidationFailure {
|
||||
valid: false;
|
||||
error: ValidationError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation result union
|
||||
*/
|
||||
export type ValidationResult = ValidationSuccess | ValidationFailure;
|
||||
|
||||
// =============================================================================
|
||||
// ROLES
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* UCAN Agent Roles
|
||||
*/
|
||||
export interface Roles {
|
||||
/** General class of entities interacting with UCAN */
|
||||
Agent: DID;
|
||||
/** Principal delegated to in current UCAN (aud field) */
|
||||
Audience: DID;
|
||||
/** Agent that performs invocation action */
|
||||
Executor: DID;
|
||||
/** Principal requesting execution */
|
||||
Invoker: DID;
|
||||
/** Principal of current UCAN (iss field) */
|
||||
Issuer: DID;
|
||||
/** Subject controlling external resource */
|
||||
Owner: DID;
|
||||
/** Agent identified by DID */
|
||||
Principal: DID;
|
||||
/** Issuer in proof chain that revokes */
|
||||
Revoker: DID;
|
||||
/** Principal whose authority is delegated */
|
||||
Subject: DID;
|
||||
/** Agent interpreting UCAN validity */
|
||||
Validator: DID;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// COMMON COMMANDS (for convenience)
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Standard CRUD command arguments
|
||||
*/
|
||||
export namespace CRUDCommands {
|
||||
export interface CreateArgs {
|
||||
uri: string;
|
||||
payload: unknown;
|
||||
headers?: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface ReadArgs {
|
||||
uri: string;
|
||||
query?: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface UpdateArgs {
|
||||
uri: string;
|
||||
payload: unknown;
|
||||
headers?: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface DeleteArgs {
|
||||
uri: string;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard messaging command arguments
|
||||
*/
|
||||
export namespace MessageCommands {
|
||||
export interface SendArgs {
|
||||
from: string;
|
||||
to: string[];
|
||||
subject?: string;
|
||||
body: string;
|
||||
cc?: string[];
|
||||
bcc?: string[];
|
||||
}
|
||||
|
||||
export interface ReceiveArgs {
|
||||
mailbox: string;
|
||||
since?: Timestamp;
|
||||
limit?: number;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* WebAssembly execution command arguments
|
||||
*/
|
||||
export namespace WasmCommands {
|
||||
export interface RunArgs {
|
||||
/** Wasm module as data URI or CID */
|
||||
mod: string | CID;
|
||||
/** Function to execute */
|
||||
fun: string;
|
||||
/** Function parameters */
|
||||
params: unknown[];
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// TYPE GUARDS
|
||||
// =============================================================================
|
||||
|
||||
export function isDID(value: unknown): value is DID {
|
||||
return typeof value === "string" && value.startsWith("did:");
|
||||
}
|
||||
|
||||
export function isCID(value: unknown): value is CID {
|
||||
return (
|
||||
typeof value === "object" &&
|
||||
value !== null &&
|
||||
"/" in value &&
|
||||
typeof (value as CID)["/"] === "string"
|
||||
);
|
||||
}
|
||||
|
||||
export function isBytes(value: unknown): value is Bytes {
|
||||
return (
|
||||
typeof value === "object" &&
|
||||
value !== null &&
|
||||
"/" in value &&
|
||||
typeof (value as Bytes)["/"] === "object" &&
|
||||
"bytes" in (value as Bytes)["/"]
|
||||
);
|
||||
}
|
||||
|
||||
export function isSuccessResult<T>(result: ExecutionResult<T>): result is SuccessResult<T> {
|
||||
return "ok" in result;
|
||||
}
|
||||
|
||||
export function isErrorResult<E>(result: ExecutionResult<unknown, E>): result is ErrorResult<E> {
|
||||
return "err" in result;
|
||||
}
|
||||
|
||||
export function isDelegation(token: Delegation | Invocation): token is Delegation {
|
||||
return "ucan/dlg@1.0.0-rc.1" in token[1];
|
||||
}
|
||||
|
||||
export function isInvocation(token: Delegation | Invocation): token is Invocation {
|
||||
return "ucan/inv@1.0.0-rc.1" in token[1];
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// UTILITY TYPES
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Extract the payload type from a UCAN envelope
|
||||
*/
|
||||
export type ExtractPayload<E extends UCANEnvelope<object>> =
|
||||
E extends UCANEnvelope<infer P> ? P : never;
|
||||
|
||||
/**
|
||||
* Create a typed invocation for a specific command
|
||||
*/
|
||||
export type TypedInvocation<C extends Command, A extends Arguments> = [
|
||||
Signature,
|
||||
{
|
||||
h: VarsigHeader;
|
||||
"ucan/inv@1.0.0-rc.1": Omit<InvocationPayload, "cmd" | "args"> & {
|
||||
cmd: C;
|
||||
args: A;
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* Create a typed delegation for a specific command
|
||||
*/
|
||||
export type TypedDelegation<C extends Command> = [
|
||||
Signature,
|
||||
{
|
||||
h: VarsigHeader;
|
||||
"ucan/dlg@1.0.0-rc.1": Omit<DelegationPayload, "cmd"> & {
|
||||
cmd: C;
|
||||
};
|
||||
}
|
||||
];
|
||||
Reference in New Issue
Block a user