MAP Docs
Concepts

Capabilities

Hierarchical capability names, caveats, delegation, and how the SecurityGateway matches them at request time.

Every operation on every protocol requires a capability. Capabilities are hierarchical strings; the security gateway matches them against the caller's resolved identity using exact / protocol-wildcard / global-wildcard semantics.

The naming scheme

map.{protocol_id}.{operation}
CapabilityGrants
map.macs.auth_negotiationExactly one operation
map.macs.*Every operation on MACS
map.*.*Every operation on every protocol (admin)
map.mind.readRead-side operations on MIND (alias for store_memory.read, etc.)

The exact-match path is preferred. Wildcards are a convenience for ops/admin tenants and for treaties that grant a counterparty an entire protocol surface.

The struct

pub struct AgentCapability {
    pub name: String,
    pub expires_at: Option<chrono::DateTime<Utc>>,
    pub limits: Option<CapabilityLimits>,
    pub caveats: Vec<String>,
}

pub struct CapabilityLimits {
    /// Per-call max spend in basis-points of tenant budget.
    pub max_per_call_bps: Option<u32>,
    /// Per-hour rate cap.
    pub max_per_hour: Option<u32>,
    /// Hard token ceiling per call (overrides MEAL default).
    pub max_tokens: Option<u32>,
}

caveats is a free-form vector of policy strings the policy engine (MAXIM) interprets. Common caveats:

  • time:09-17 — only valid 09:00–17:00 UTC
  • jurisdiction:eu — only valid for EU-tagged requests
  • weekly_budget:5000 — bound to a weekly spend cap

Where capabilities come from

ResolvedAgentIdentity.capabilities
    = OAS_document.declared_capabilities
    + Aegis.active_delegations(did)
    + MOAT.active_treaty_capabilities(tenant, foreign_tenant)
    - revoked

The composition happens during MACS::derive and runs every request. Caching is per-tenant with a short TTL (default 60s) so revocations propagate quickly.

How matching works

fn is_operation_allowed(caps: &[AgentCapability], protocol: &str, op: &str) -> bool {
    let exact   = format!("map.{}.{}", protocol.to_lowercase(), op);
    let proto_w = format!("map.{}.*",  protocol.to_lowercase());
    let global  = "map.*.*";

    caps.iter()
        .filter(|c| !c.is_expired())
        .filter(|c| c.caveats_satisfied_in_current_context())
        .any(|c| c.name == exact || c.name == proto_w || c.name == global)
}

This runs at Stage 4 of the pipeline. A miss returns CoreError::CapabilityDenied { protocol, operation }.

Wildcard rules

  • map.* alone — does not match. Wildcards must terminate a leaf segment.
  • map.macs.* — matches every MACS operation.
  • map.*.read — does not match. Cross-protocol wildcards are not allowed.
  • map.*.* — admin escape hatch. Reserved for ops tenants.

The restriction on map.*.read is deliberate. It prevents accidental over-granting when the same operation name appears in multiple protocols.

Reading capabilities inside a protocol module

fn require_capability(id: &ResolvedAgentIdentity, op: &str) -> Result<(), ProtocolError> {
    let needed = format!("map.{}.{}", "marc", op);
    if id.has_capability(&needed) {
        Ok(())
    } else {
        Err(ProtocolError::MissingCapability(needed))
    }
}

The engine has already checked at Stage 4 — but protocols often re-check inside invoke to enforce fine-grained permissions (e.g., MARC::synthesize may require both map.marc.synthesize and map.mind.snapshot to bind the world model).

Delegations

Via Aegis::delegate, an entity can issue a bounded capability to another entity. The delegation is a signed token that includes:

pub struct DelegationToken {
    pub from_did: String,
    pub to_did:   String,
    pub capabilities: Vec<AgentCapability>,
    pub max_redelegation_depth: u32,  // anti-amplification
    pub expires_at: chrono::DateTime<Utc>,
    pub revocation_url: Option<String>,
    pub signature: Signature,
}

The no-amplification rule is enforced at delegation time: the delegate cannot receive capabilities the delegator does not hold. Aegis::delegate rejects amplifying tokens.

Treaty capabilities

A MOAT treaty grants a foreign tenant a bounded capability set inside your tenant. The treaty is a signed document on both sides; MACS::derive includes treaty grants in the composed capability set when the caller's tenant matches the foreign side.

# Treaty example (yaml)
treaty:
  parties:
    - tenant: org_acme
    - tenant: org_globex
  grants_to_globex:
    - map.mind.recall_memory
    - map.maven.cite
    - map.made.economic_contract_settle (caveats: [weekly_budget:50000])
  expires_at: 2026-12-31T00:00:00Z

Treaty grants are revoked instantly by MOAT::terminate; all in-flight requests complete, new requests fail at security gating.

Treaties unlock the legitimacy loop. Two institutions can collaborate without merging; their audit chains stay separate; the boundary is policed by MOAT. The price of a treaty is the discipline of declaring it.

See also

On this page