Skip to content
Portal Control Protocol

Application

An application in PCP is represented by an AppDescriptor. The daemon builds one for each detected application during the discovery pipeline, and the descriptor is what RegistryQuery::Apps returns to clients.

The descriptor carries the app’s identity, its detection metadata (how it was found, how confident the daemon is), the list of capability IDs it exposes, and an optional manifest for Tier 1 apps. It does not carry process-level details like PIDs or command lines. Those are implementation concerns of the detection adapters, not part of the protocol.

{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "AppDescriptor",
"type": "object",
"required": ["app_id", "name", "capabilities", "detected_method", "detection_confidence"],
"properties": {
"app_id": {
"type": "string",
"description": "Reverse-DNS application identifier."
},
"name": {
"type": "string",
"description": "Human-readable application name."
},
"capabilities": {
"type": "array",
"items": { "type": "string" },
"description": "Fully qualified capability IDs this app exposes."
},
"detected_method": {
"type": "string",
"enum": ["desktop", "atspi2", "wine", "simulated"],
"description": "How the daemon discovered this application."
},
"detection_confidence": {
"type": "number",
"minimum": 0.0,
"maximum": 1.0,
"description": "Confidence score from the detection adapter."
},
"metadata": {
"type": "object",
"additionalProperties": true,
"description": "Arbitrary metadata from the detection adapter."
},
"manifest": {
"type": ["object", "null"],
"description": "Full CapabilityManifest for Tier 1 apps. Null for Tier 2 and Tier 3."
}
}
}

The detected_method field indicates how the daemon found this application. The four values correspond to the detection priority chain:

Method Tier Description
desktop Tier 1 Static discovery via desktop entry files, signed manifests, and binary probing
atspi2 Tier 2 Full accessibility-tree walk producing derived per-element capabilities
wine Tier 2 MSAA/UIA accessibility bridge for Windows applications
simulated Tier 3 Universal fallback using coordinate and input synthesis

Tier 1 apps ship a manifest and implement the Tier 1 server trait, so they get typed parameters and structured return values. Tier 2 apps get capabilities derived automatically from the accessibility tree. Tier 3 apps receive only basic window-management capabilities via input simulation.

The Domain enum defines three privilege levels. Every capability has a domain, and every caller has a domain. A caller can only reach capabilities at or below its own domain level.

pub enum Domain {
App, // lowest -- app capabilities, registry reads, event subscriptions
Compositor, // mid -- App plus surface and zone management
System, // highest -- Compositor plus audio, network, filesystem, power
}

The privilege ordering is strict: App < Compositor < System. A capability in the System domain cannot be invoked by a caller at the App domain. This containment model prevents lower-privilege code from reaching system-level operations.

An Intent represents a caller’s desire to perform an action. System Intelligence constructs intents from natural language or other input, and the daemon resolves them into concrete capability invocations.

pub struct Intent {
pub action: String, // capability action to perform
pub target_app: Option<String>, // resolved by the pipeline if absent
pub parameters: serde_json::Value, // capability-specific parameters
pub domain: Domain, // caller's domain
pub priority: i32, // higher means more important
}

When target_app is None, the daemon runs target resolution to pick the right app based on session context, user defaults, and recent usage history. The priority field orders concurrent intents when System Intelligence issues multiple requests at once.

Every capability invocation returns an ExecutionResult. It captures whether the invocation succeeded, what it produced, how long it took, and where it was audited.

pub struct ExecutionResult {
pub success: bool,
pub output: serde_json::Value,
pub duration_ms: u64,
pub audit_id: Option<u64>,
pub error: Option<String>,
}
Field Description
success True if the capability completed without error
output Capability-specific return data
duration_ms Wall-clock execution time in milliseconds
audit_id Identifier in the audit journal, if the invocation was audited
error Human-readable error description when success is false
{
"app_id": "com.example.present",
"name": "Present",
"capabilities": [
"app.com.example.present.slide.add",
"app.com.example.present.slide.remove",
"app.com.example.present.deck.list"
],
"detected_method": "desktop",
"detection_confidence": 1.0,
"metadata": {
"tier": "1",
"display_target": "glasses"
},
"manifest": null
}

This example shows a Tier 1 app discovered through desktop entry scanning. The detection_confidence of 1.0 means the detection adapter is fully certain. The capabilities list contains fully qualified IDs in domain.app.action format. The manifest field is null here, but a real Tier 1 response would include the full manifest object when the client queries individual app details.

For Tier 2 apps, detected_method would be "atspi2", the capabilities list would contain adapter-derived IDs (like app.com.example.mail.search), and the manifest would always be null.

Last updated: