CAPNS Documentation

Capability Definition and Matching System for Plugin Architectures

Overview

CAPNS (Capability Namespace Registry) is a formal capability framework designed for plugin architectures that need dynamic capability discovery, matching, and validation. It solves the problem of how distributed systems can advertise, discover, and match capabilities with proper specificity handling and runtime validation.

Core Problems Solved

  • Dynamic Capability Discovery - Systems can discover what operations plugins/providers support at runtime
  • Intelligent Routing - Request routing based on capability matching with preference for more specific implementations
  • Cross-Language Interoperability - Consistent capability definitions across Rust, Go, and Objective-C
  • Validation and Schema Compliance - Runtime validation of inputs/outputs against capability schemas
  • Plugin Architecture Scaling - Managing capabilities across many providers without manual registration

Cap URN Format Specification

Basic Format & Structure

1

Case Insensitivity

All input is normalized to lowercase for storage and comparison.

cap:ACTION=Generate → cap:action=generate
2

Tag Order Independence

Tags are sorted alphabetically by key in canonical form.

cap:target=doc;action=gen → cap:action=gen;target=doc
3

Mandatory Prefix

Must always start with cap: prefix.

cap:action=generate;format=pdf
4

Tag Separator

Tags separated by semicolons (;).

cap:action=extract;target=metadata;format=json
5

Optional Trailing Semicolon

Trailing semicolon presence/absence doesn't matter.

cap:action=validate; = cap:action=validate

Character & Content Rules

6

Character Restrictions

Alphanumeric, _, -, /, ., :, and * (values only) allowed.

cap:url=https://api/v1;path=/user/data
7

Tag Structure

= separates key/value; ; separates pairs; : only special in prefix.

cap:service=api:v1;endpoint=/data
8

No Special Tags

No reserved tag names - any key is valid.

cap:custom_property=my_value;special_tag=data
9

Canonical Form

Lowercase, alphabetically sorted tags, no trailing semicolon.

cap:action=generate;ext=pdf;target=thumbnail

Matching & Wildcard Rules

10

Wildcard Support

* accepted only in values, matches any value for that key.

cap:action=*;format=pdf matches cap:action=generate;format=pdf
11

No Empty Components

Both key and value must be non-empty after trimming.

❌ cap:action=;target=doc or cap:=value
12

Matching Specificity

More tags = more specific. cap: matches all URNs.

cap: → cap:action=* → cap:action=generate
13

Exact Tag Matching

URN matches only if it has specified tag with specified value.

cap:action=generate matches cap:action=generate;ext=pdf
14

Subset Matching

Only specified tags affect matching; extra tags are ignored.

cap:action=generate matches cap:action=generate;other=ignored

Validation & Error Rules

15

Duplicate Keys

Duplicate keys result in error - no implicit override.

❌ cap:action=gen;action=create (error)
16

UTF-8 Support

Full UTF-8 within allowed character restrictions.

cap:action=générer;locale=français
17

Numeric Values

Keys cannot be purely numeric; values can be.

✓ cap:version=2;port=8080 ❌ cap:123=value
18

Empty Cap URN

cap: with no tags is valid universal matcher.

cap: matches any capability URN
19

Length Restrictions

Must be valid URL: https://capns.org/{cap_urn}

Practical limit ~2000 characters
20

Wildcard Restrictions

* forbidden in keys, only allowed in values.

✓ cap:format=* ❌ cap:*=value
21

Colon Treatment

/ and : treated as normal characters after prefix.

cap:url=http://api:8080/v1;path=/users

Matching Algorithm

The matching system implements sophisticated logic for determining if a capability can handle a request:

pub fn matches(&self, request: &CapUrn) -> bool {
    // Check all tags that the request specifies
    for (request_key, request_value) in &request.tags {
        match self.tags.get(request_key) {
            Some(cap_value) => {
                if cap_value == "*" {
                    // Cap has wildcard - can handle any value
                    continue;
                }
                if request_value == "*" {
                    // Request accepts any value - cap's specific value matches
                    continue;
                }
                if cap_value != request_value {
                    // Cap has specific value that doesn't match request's specific value
                    return false;
                }
            }
            None => {
                // Missing tag in cap is treated as wildcard - can handle any value
                continue;
            }
        }
    }
    true
}

Matching Rules

  1. Missing tags are wildcards - A capability without a specific tag can handle any value for that tag
  2. Explicit wildcards - Using * as a value explicitly indicates "any value"
  3. Subset matching - Capabilities can be more specific than requests
  4. Exact matching - When both specify the same non-wildcard value

Wildcard System

Types of Wildcards

Explicit wildcards
action=generate;format=* (can handle any format)
Missing tag wildcards
action=generate (missing format tag = can handle any format)

Practical Examples

// Capability: action=extract;format=pdf;target=metadata
// Can handle:
//   action=extract                    (subset match)
//   action=extract;format=*          (wildcard request)
//   action=extract;format=pdf        (exact match)
// Cannot handle:
//   action=extract;format=docx       (format conflict)
//   action=generate                  (action conflict)

Specificity and Selection

Specificity Calculation

pub fn specificity(&self) -> usize {
    // Count non-wildcard tags
    self.tags.values().filter(|v| v.as_str() != "*").count()
}

Best Match Selection

  • Find all capabilities that can_handle() the request
  • Select the one with highest specificity score
  • Enables intelligent provider selection (more specific = preferred)

Example Selection Process

// Request: cap:action=conversation;language=en
// Available:
// 1. cap:action=conversation (generic, score=1)
// 2. cap:action=conversation;language=en;type=constrained (specialized, score=3)
// → Selects provider #2

Command Chaining

Capabilities define input/output schemas enabling automated pipeline construction. Commands can be chained without manual integration work.

cap:action=extract;target=pages
cap:action=generate;target=thumbnail
cap:action=create;target=gallery

Each capability's output schema is validated against the next capability's input requirements, ensuring type safety across the pipeline.

Integration Patterns

// Provider Registration
provider_registry.register_caps("my-provider", vec![
    extract_metadata_cap(),
    generate_thumbnail_cap(),
]);

// Client Request
let provider = provider_registry.find_provider("cap:action=extract;format=pdf")?;
let result = provider.execute(args).await?;

Validation and Schema Compliance

Each capability defines argument schemas with validation rules. Output schemas ensure type safety across capability chains.

"arguments": {
  "required": [
    {
      "name": "file_path",
      "arg_type": "string", 
      "arg_description": "Path to the document file to process",
      "validation": {
        "pattern": "^[^\\0]+$",
        "min_length": 1
      }
    }
  ],
  "optional": [
    {
      "name": "max_depth",
      "arg_type": "integer",
      "arg_description": "Maximum outline depth to extract (1-10)", 
      "validation": {
        "min": 1,
        "max": 10
      }
    }
  ]
}

Validation Workflow

  1. Local validation against argument/output schemas
  2. Registry validation to ensure canonical compliance
  3. Cross-language compatibility through shared schemas

Cross-Language Implementation

Language Parity

  • Rust - Core implementation with full feature set
  • Go - Feature-complete with idiomatic Go patterns
  • Objective-C - Native Apple ecosystem support

Consistent APIs

All implementations provide identical functionality:

// Rust
let cap = CapUrn::builder().action("extract").format("pdf").build();

// Go  
cap := capns.NewUrn().Action("extract").Format("pdf").Build()

// Objective-C
CSCapUrn *cap = [CSCapUrn builderWithAction:@"extract" format:@"pdf"];

Common Features

  • Builder patterns for URN construction
  • Matching and specificity algorithms
  • Serialization/deserialization
  • Registry integration

Registry Integration and Caching

Registry Architecture

  • Central registry at https://capns.org for canonical capability definitions
  • Local-first caching with 24-hour TTL to minimize network requests
  • In-memory + disk caching for performance
  • Automatic fallback from cache to network to ensure availability
Cache Location: ~/.cache/capns/
Format: {hash}.json (SHA256 of URN string)
TTL: 24 hours
Fallback: Network → Local → Error

API Reference

Lookup Capability

GET https://capns.org/{capurn}

Look up a capability definition by its CAPURN.

Example Request:

GET https://capns.org/cap:action=generate;format=pdf

Example Response:

{
  "urn": {
    "tags": {
      "action": "generate",
      "format": "pdf"
    }
  },
  "cap_description": "Generate PDF documents",
  "command": "pdf-generator",
  "arguments": {
    "required": [
      {
        "name": "input",
        "arg_type": "string",
        "arg_description": "Input content or file path",
        "cli_flag": "--input",
        "validation": {
          "min_length": 1
        }
      }
    ],
    "optional": []
  },
  "output": {
    "output_type": "binary",
    "content_type": "application/pdf",
    "output_description": "Generated PDF document"
  },
  "accepts_stdin": true
}

List All Capabilities

GET https://capns.org/api/capabilities

Get a list of all registered capabilities.

Response Format:

[
  {
    "urn": { "tags": { "action": "extract", "target": "metadata" } },
    "cap_description": "Extract document metadata",
    "command": "extract-metadata"
  },
  ...
]