# Platform Capability Schema — Layer 3 Domain Entity Type # KNO Schema Version: 0.2.0 # CHANGELOG: # 0.2.0 (M52 P4.1, #2139): Add `visibility: public` collection default per REQ-18. # Platform capability entities are public reference knowledge # consumed via the four-surface contract. # Manifest version: see `version:` below + `_history.changelog`. Most recent # entry: 2.2.0 (M55 #2406, 2026-05-04) — add `provenance{}` property # (publisher_possibility_xri + contributors[] + version_history[]) to enable # capability authorship attestation and signed contributor history. # # A Platform Capability is an installable, composable feature that adds # functionality to a Possibility. It is the top-level manifest describing # what a Capability does, what it needs, and how it integrates. # # EXTENDS: document-schema.kno (which composes identity, history, quality) # # RELATIONSHIP TO EXISTING SCHEMAS: # - capability-schema.kno: Permission tuples ({action, resource, constraints}). # Platform Capabilities REFERENCE these via `required_permissions[]`. # - agent-card-schema.kno: A2A discovery metadata. Agent Cards are DERIVED # from Platform Capabilities via thin transformation (P10). # - workflow-schema.kno: Installation step sequences. Platform Capabilities # REFERENCE workflows via `lifecycle.setup_workflow` XRI. # - role-schema.kno: Actor definitions. Platform Capabilities CONTAIN roles # for their agent personas via `_contains.roles`. # - guide-schema.kno: Human-readable instructions. Platform Capabilities # link to guides via `relationships.documented_by`. # # GAP-02 NAMING RESOLUTION: # The word "capabilities" is overloaded across 3 schemas: # - capability-schema: Permission tuples → referenced as `required_permissions` # - agent-card-schema: A2A protocol features → referenced as `a2a.protocol_capabilities` # - role-schema: Role actions → unchanged (internal to role files) # The Platform Capability IS the entity — no `capabilities` field on itself. # # THREE-GATE TEST (validated in gap-analysis.md § Schema Audit §3): # Gate 1 (Distinctness): YES — no existing schema covers tool definition, # UI resources, permissions, sandbox, composition, lifecycle together. # Closest (agent-card) covers ~30% and is semantically an A2A protocol type. # Gate 2 (Reusability): YES — 15+ Capabilities identified across 3 tiers # (Auth, CMS, Analytics, Email, AI Agent, etc.), eventually 50-100+. # Gate 3 (Clarity): YES — resolves the `capabilities` triple naming collision # by being the top-level concept that contains/references the others. # # DESIGN DECISIONS: # DD-CAP-01: Platform Capability is the source of truth; Agent Card, MCP tools, # Library listing, and installation manifests are derived views (P10). # DD-CAP-02: `atoms[]` are the platform building blocks a Capability provisions # (realm, bucket, domain, etc.) — the physical resources it creates. # DD-CAP-03: v1 includes STANDARD + RICH tier fields plus distribution metadata # and submission lifecycle. FEDERATED tier fields (theming, # cross-Possibility sharing) are deferred to v2. Note: AD-04 overrides # part of this deferral — `data_requirements[]` ships in v1 as a # declaration field (replaces deferred `data_bindings`). # DD-CAP-04: `runtime.primary` defaults to `a2ui` — A2UI is the v1 strategic bet. # DD-CAP-05: `history_policy` is designed now but TerminusDB integration is v2. # DD-CAP-06: Every Capability declares its auth context via `auth_context{}`. # See spec AD-01 (Two-Context Auth Model) and AD-02. Organizer auth # is required by default; end-user auth defaults to `none`. # DD-CAP-07: Capabilities declare data store and connector dependencies via # `data_requirements[]`. See spec AD-04. v1 provider is always # `possibility.space`; portability designed for v2+. # DD-CAP-08: Multi-version `installed_capabilities[]` for blue-green # upgrades (P3 #1842, Capabilities v2). The array MAY contain # multiple entries with the same `capability_slug` during a # blue-green migration. The entry without a `superseded_by` # field is the **primary** (the version M32 callers see by # default). An entry WITH `superseded_by: ` is # a **legacy** version awaiting decommission (#1843). All # find-by-slug queries MUST go through # `findInstalledCapabilityVersion()` in # `services/pspace-api/src/lib/possibility-entity.ts` (a # drift-guard enforces this). Atoms in a `superseded_by`- # marked entry use a `version_tag`-suffixed atom-id during # blue-green to avoid collisions with the primary's atoms. # ============================================================================= # SCHEMA DECLARATION (RFC-007) # ============================================================================= $schema: kno@0.0.9 # ============================================================================= # IDENTITY (Layer 1) # ============================================================================= id: 01KP3GXWMR8NVJQY5ZH2B6KFDT slug: platform-capability-schema type: spec version: 2.2.0 # ============================================================================= # VISIBILITY DECLARATION (REQ-18) — collection default # ============================================================================= # Platform-capability entities (content/capabilities/*.kno) are public reference # knowledge by default — they describe installable, composable platform features. # Per REQ-18, individual entities MAY override with their own `visibility:` field # (last-write-wins at the entity level). Drives the four-surface contract per # kno-system_architecture.md § Agent Surface Integration and # public-surface-parity.instructions.md. visibility: public # ============================================================================= # STANDARD TIER # ============================================================================= title: "Platform Capability Schema" purpose: | Define the schema for Platform Capabilities — installable, composable features that add functionality to a Possibility. **What is a Platform Capability?** A Platform Capability is a structured manifest that describes: - What the Capability does (skills, tools) - What it needs (permissions, dependencies) - How it renders (A2UI surfaces, MCP Apps resources) - How it installs and manages its lifecycle - What platform building blocks (atoms) it provisions **Derived Views (P10 Thin Transformations):** The Platform Capability .kno is the source of truth. All protocol surfaces are projections: | Derived View | Source Fields | Endpoint | |---------------------|-------------------------------------------|---------------------------------------| | A2A Agent Card | `a2a` + `skills` + title/purpose | `/.well-known/agent/{slug}.json` | | MCP Tool Registry | `skills[]` | MCP server tool list | | Library Listing | title + purpose + `distribution` | Capability catalog API | | Install Manifest | `required_permissions` + `lifecycle` | Installation consent screen | **Relationship to Existing Schemas:** | Schema | Relationship | How Referenced | |---------------------|--------------------|------------------------------------| | capability-schema | references | `required_permissions[]` uses its vocabulary | | agent-card-schema | derives | Agent Card projected from this entity | | workflow-schema | references | `lifecycle.setup_workflow` XRI | | role-schema | contains | `_contains.roles` for agent personas | | guide-schema | documented_by | Linked via relationships | **Layer 3 Position:** Platform Capability extends document (Layer 2), which composes identity, history, and quality (Layer 1). # ============================================================================= # RICH TIER — Provenance & Taxonomy # ============================================================================= provenance: origin: id: 01KP3GXWMR8NVJQY5ZH2B6KFDT timestamp: "2026-04-07T00:00:00Z" tool: manual taxonomy: topics: - capabilities - platform-features - installation - lifecycle - a2a - composition keywords: - platform-capability - capability - install - atoms - skills - permissions - lifecycle - a2ui - blueprint # ============================================================================= # RICH TIER — Relationships # ============================================================================= relationships: extends: - xri: "kno://specs/document-schema" reason: "Layer 2 base type for all documents" depends_on: - xri: "kno://specs/kno-spec" reason: "Conforms to KNO format specification v0.0.9" composes: - xri: "kno://specs/identity-schema" reason: "Layer 1: id, slug" - xri: "kno://specs/history-schema" reason: "Layer 1: _history, changelog" - xri: "kno://specs/quality-schema" reason: "Layer 1: quality, validation" related_to: - xri: "kno://specs/capability-schema" reason: "Permission tuples referenced via required_permissions[]" - xri: "kno://specs/agent-card-schema" reason: "Agent Cards derived from Platform Capability entities (P10)" - xri: "kno://specs/workflow-schema" reason: "Installation workflows referenced via lifecycle.setup_workflow" - xri: "kno://specs/role-schema" reason: "Agent personas contained within Platform Capability entities" - xri: "kno://specs/guide-schema" reason: "Setup guides linked via documented_by relationship" - xri: "kno://specs/possibility-schema" reason: "Capabilities are installed within Possibilities" documented_by: - xri: "pspace://api/capabilities-catalog-api" reason: "Catalog browsing and discovery endpoints" - xri: "pspace://api/capabilities-lifecycle-api" reason: "Lifecycle state management, consent, and A2UI surface endpoints" - xri: "pspace://api/capabilities-install-api" reason: "Async install/uninstall/retry/resume/upgrade orchestration endpoints" - xri: "pspace://api/capabilities-submissions-api" reason: "Publisher submission pipeline endpoints" - xri: "pspace://api/capabilities-approval-api" reason: "Admin review, decision, and publish endpoints" - xri: "pspace://api/capabilities-validate-api" reason: "Pre-submission .kno manifest validation endpoint" - xri: "pspace://api/capabilities-test-harness-api" reason: "Deep pre-submission test harness endpoint" - xri: "pspace://api/capabilities-publisher-verification-api" reason: "Publisher domain verification endpoints" enables: - xri: "kno://content/capabilities/*" reason: "All Capability instances conform to this schema" # ============================================================================= # RICH TIER — Quality # ============================================================================= quality: completeness: 0.80 last_reviewed: "2026-04-07" review_status: draft reviewed_by: "claude" # ============================================================================= # HISTORY (P9 Temporal) # ============================================================================= _history: retention: full format: changelog changelog: - version: "2.2.0" date: "2026-05-04" author: "claude" summary: "M55 INTEG-1.2 (#2406): add top-level `provenance{}` property for capability authorship attestation" changes: - "Added top-level `provenance{}` property to the Platform Capability instance schema (additive, MINOR bump). Purpose: make it explicit and machine-checkable WHICH Possibility published a capability and WHO contributed to it across versions. This is the manifest-side half of M55 Epic #2404; the orchestrator-side append-only enforcement ships in #2413." - "Subfields: `publisher_possibility_xri` (REQUIRED at submission time via `capability-submission-validator.ts` + commit-time via `scripts/lint-capability-provenance.ts`; OPTIONAL at the schema layer to keep the bump additive). XRI of the owning Possibility — the tenant that signed the publish. Format: `pspace://possibility/` or `pspace://possibility:` per RFC-013." - "Subfield: `contributors[]` — append-only list of { user_xri, possibility_xri, role: author|reviewer|approver, at: ISO8601, signature_jwt }. Append-only ENFORCEMENT lives in the orchestrator (#2413); this schema only declares the shape." - "Subfield: `version_history[]` — list of { version (semver), at (ISO8601), author_user_xri, change_summary, signature_jwt? }. Provides an inline minimal version trail; full VCS backing remains TerminusDB per Capabilities v2 deferral." - "`signature_jwt` is signed with the per-tenant key issued by #2409. That issuance is out of scope for this schema bump — the schema defines only the field shape. Validators that don't yet have access to per-tenant JWKS should treat the field as opaque pending #2409." - "NOT made required at the schema (`spec.schema.required`) layer to keep this an additive change — pre-existing `submission_status: draft` manifests don't fail loading. The submission-pipeline validator treats `provenance.publisher_possibility_xri` as required at `submitted` (and beyond) status." - "Backfills the missing 2.1.0 changelog entry slot: the previous `version: 2.1.0` bump shipped without a changelog row (caught during this edit). The 2.1.0 → 2.2.0 jump is intentional rather than a re-do: it preserves the `version:` field's existing 2.1.0 value as a reference point and adds 2.2.0 as the next additive step." - version: "2.0.0" date: "2026-04-25" author: "claude" summary: "Capabilities v2 schema cleanup: remove deprecated distribution.{category,tags} (Epic audit follow-up)" changes: - "Removed `distribution.category` (singular, free-form). Replaced by top-level `categories[]` (closed enum, max 5) added in 1.4.0. The transition path was: 1.4.0 introduced `categories[]` while retaining `distribution.category` for BC; 2.0.0 removes the deprecated form. New manifests MUST populate top-level `categories[]`." - "Removed `distribution.tags[]`. Replaced by top-level `keywords[]` (open, max 12) added in 1.4.0. Same transition pattern as categories." - "Both pre-existing manifests (auth-realm-capability.kno, storage-bucket-capability.kno) populated with top-level `publisher{}`, `categories[]`, `keywords[]`, `featured` and had their legacy `distribution.{category,tags}` blocks removed in the same commit. Manifest version: 1.0.0 → 2.0.0; $schema pin @1.2.0 → @2.0.0. Composition drift-guard EXPECTED_SCHEMA constant migrated in parallel. Capability-composition-paired sample manifests bumped to @2.0.0." - "Validator (`capability-submission-validator.ts`) updated: `distribution.category` warning replaced by `categories[]` warning; `distribution.tags` warning replaced by `keywords[]` warning; $schema warning recommends `platform-capability@2.0.0`." - "Transformer (`lib/kno/transformers/platform-capability.ts`) updated: catalog projection now reads `entity.categories[0]` and `entity.keywords` instead of `entity.distribution?.category` and `entity.distribution?.tags`. The fallback to `distribution.*` fields was removed entirely — NO legacy-field fallback path (per M33 P4 futro PE5 user directive 2026-04-25)." - "MAJOR bump justification: removes fields that were retained for BC in 1.4.0. Per user directive 2026-04-25 (“no fear of breaking changes; no active users; long-term platform health”), the dual-field period is closed without a deprecation cycle. All existing manifests + sample manifests migrated in the same commit. The remaining BC concerns (3 site callers, 1 catalog endpoint, 8+ tests reading `distribution.category`/`tags`) are scoped to P4 #1846's REPLACE work — they are explicitly NOT maintained by this schema bump." - "Epic-tier audit cross-reference: this schema bump is one deliverable of the 2026-04-25 P0–P3 epic audit (`logs/audits/2026_04_25-epic-cap-v2-p0-p3-upgrade-lifecycle/`). Audit § 4 Spec Drift item: P1 was AC-met but data-incomplete for the new top-level fields. This bump closes that gap by (a) populating the manifests, and (b) making the v2 fields the ONLY source of truth." - "Renumbered during M33 → main merge integration (2026-04-26): our v2 P1 entry was originally 1.2.0 + breaking change as 2.0.0. Main had independently bumped 1.0.0 → 1.1.0 (PL-007/PL-009 B) → 1.2.0 (PL-008) → 1.3.0 (#1554, the entry below this one). To preserve a linear version history, our v2 P1 entry was renumbered 1.2.0 → 1.4.0, leaving the 2.0.0 jump (this entry) intact as the breaking REPLACE-not-coexist removal of distribution.{category,tags}." - version: "1.4.0" date: "2026-04-24" author: "claude" summary: "Capabilities v2 M33 Phase 1: compatibility + publisher + categories + keywords + featured (#1833)" changes: - "Added top-level compatibility{} block: requires_pspace_version (semver range), deprecated (boolean), deprecation_notice (string), deprecated_from (semver), end_of_life (date). Enables the Install gate to check platform compatibility and the Library backend to surface deprecation state." - "Added top-level categories[] (closed enum, max 5): authentication, authorization, analytics, communication, storage, ai, cms, commerce, developer-tools, identity, integration, messaging, monitoring, search, security, workflow. As of schema 2.0.0, this is the ONLY classification field; the legacy `distribution.category` (singular, free-form) was removed." - "Added top-level keywords[] (open, max 12). Complements categories[] for fine-grained search. As of schema 2.0.0, this is the ONLY search-tag field; the legacy `distribution.tags` was removed." - "Added top-level publisher{} (id + tier). Three tiers: platform (auto-verified via repo commit path), verified (signed publisher key, gated on Auth 7), community (self-declared, no signature). Drives Library trust signalling and write-path gating." - "Added top-level featured (boolean, default false). Editorial promotion flag for Library homepage + featured collections. Set by platform publishers only." - "Bumped $schema const from `platform-capability@0.8.0` to `platform-capability@1.4.0` (originally `@1.2.0` pre-merge-renumber). Both pre-existing manifests (content/capabilities/auth-realm-capability.kno, content/capabilities/storage-bucket-capability.kno) migrated in the same commit: manifest-level version: 0.5.0 / 0.4.0 → 1.0.0 (post- spec-baseline); $schema pin migrated. Composition drift-guard EXPECTED_SCHEMA constant migrated in parallel. capability-composition-drift-guard.test.ts and capability-dependency-drift-guard.test.ts verified passing." - "MINOR bump justification — same pattern as 1.0.0→1.1.0 (B #1554): tightens enforcement to match long-standing author convention (no existing consumer depends on the pre-1.4.0 shape in a way the migration breaks); all existing manifests migrated in the same commit; no external consumer breaks." - "Epic A § 0.7 v1.18.0 cross-reference: the version-qualified XRI extension `pspace://capability/{slug}@{version_range}` inherits the documented slug-keyed canonical form's bedrock-departure justification unchanged. Parser regex extension lands in P1 Task 2 (#1834); behavioural destructure (string | null → { slug, range } | null) lands in P2 Task 1 (#1836). Version field remains required." - "Renumbered from 1.2.0 → 1.4.0 during M33 → main merge integration (2026-04-26) to slot after main's 1.3.0 (#1554) entry. Main had independently used 1.2.0 for PL-008 (skills[].invocation). The original 2.0.0 break (above) is preserved." - version: "1.3.0" date: "2026-04-25" author: "claude" summary: "Canonical XRI form for auth_context.depends_on_capability (#1554)" changes: - "auth_context.depends_on_capability: replaced kno:// example with canonical pspace://capability/{slug} form" - "auth_context.depends_on_capability: added pattern constraint `^pspace://capability/[a-z][a-z0-9-]*$` (validator tightened in parallel; bare slugs and other schemes are now rejected, not normalized)" - "Decision documented in docs/architecture/capability-dependency-identity.md" - "MINOR bump: tightens enforcement to match long-standing validator behaviour; the previously-documented kno:// example was never accepted, so this clarifies documentation rather than breaking live authors. Bare-slug content migrated in the same PR (storage-bucket-capability.kno)." - "Renumbered from 1.1.0 → 1.3.0 during merge of design-reviewer-v3 into main; main had already independently bumped to 1.1.0 (PL-007 + PL-009 B) and 1.2.0 (PL-008)." - version: "1.2.0" date: "2026-04-24" author: "claude" summary: "PL-008 (#1826): skills[].invocation for handler-endpoint discoverability" changes: - "Added optional skills[].invocation object — declares how a skill is invoked: rest{method,path}, mcp_tool name, or discovery_only marker" - "Drives PL-008 (#1826): cap_* MCP discovery tools now return the invocation pointer so agents navigate from skill name to handler endpoint without guessing" - "Strict-mode lint (scripts/lint-capability-skills.ts) requires every skill to declare invocation; net-new skills without it fail CI" - "Field is additive; existing entities backfilled in the same change" - version: "1.1.0" date: "2026-04-24" author: "claude" summary: "PL-007 + PL-009 B (#1825): tenant_description + opacity_scope" changes: - "Added optional tenant_description at top level (tenant-facing alternative to purpose for MCP/A2A/Library projections)" - "Added optional skills[].tenant_description (preferred by MCP tool and A2A skill projections)" - "Added optional opacity_scope enum (platform-internal|tenant-facing) — distinct from capability_type (data sovereignty); controls provider-opacity lint scope" - "Both fields are additive; existing entities remain valid" - "Provider Opacity policy applies to tenant_description only; purpose/description remain admin/internal source of truth" - version: "0.8.0" date: "2026-04-15" author: "claude" summary: "External capability schema fields for Brownfield E2E (#1363)" changes: - "Added capability_type enum (internal|external) as top-level discriminator" - "Added a2a.adapter_version for pspace adapter protocol versioning" - "Added a2a.health_check_url for external capability health probes (60s default)" - "Added a2a.service_token_ref for OpenBao secret path references" - "Added a2a.circuit_breaker_config{} with failure_threshold, recovery_timeout, check/eval intervals" - "Documented 6 Agent Card ↔ .kno consistency rules (adapter contract § 3.5)" - "Updated a2a.endpoint_url description for internal vs external usage" - "All new fields are optional — existing internal capabilities remain valid" - version: "0.7.1" date: "2026-04-15" author: "claude" summary: "Audit PL-002: document node property in runtime_requirements" changes: - "Added node semver constraint to runtime_requirements (already validated by submission validator, #1370)" - version: "0.7.0" date: "2026-04-15" author: "claude" summary: "Greenfield E2E: runtime_requirements, data-store atom type, publisher verification" changes: - "Added runtime_requirements{} for platform version and service compatibility (#1332)" - "Added data-store to atom type enum for per-capability PostgreSQL schema provisioning (#1333)" - "Added publisher_verification_status field for domain verification state (#1329)" - "Added permission proportionality validation docs to required_permissions (#1331)" - "Added documented_by link to capabilities-publisher-verification-api" - version: "0.6.0" date: "2026-04-09" author: "claude" summary: "Phase 3 audit: upgrading lifecycle state, concurrent protection, persona wiring" changes: - "Added upgrading to lifecycle.states enum (PL-003, #1292)" - "Documented lifecycle FSM transition: installed/active → upgrading → installed" - "Concurrent installation protection via operation lock (PL-006)" - "Provisioner persona identity wired into activity events (PL-007)" - "Submission SQL refactored to fragment composition (PL-008)" - version: "0.5.0" date: "2026-04-09" author: "claude" summary: "Add revisions_requested to review.decision enum for submission workflow" changes: - "Added revisions_requested to review.decision enum (resolves #1259)" - "Supports three-outcome review: approved, rejected, or revisions_requested" - "Enables iterative review cycles before final approval" - version: "0.4.0" date: "2026-04-08" author: "claude" summary: "Add authorization_details[] for OAuth 2.1 RAR (RFC 9396) support" changes: - "Added authorization_details[] for structured RAR objects (resolves #1234)" - "Maps required_permissions to RFC 9396 Rich Authorization Requests format" - "Supports token-scoped consent and least-privilege access control" - version: "0.3.0" date: "2026-04-07" author: "claude" summary: "Add auth_context and data_requirements fields per AD-01 through AD-04" changes: - "Added auth_context{} for Two-Context Auth Model (DD-CAP-06, spec AD-01/AD-02)" - "Added data_requirements[] for PDS-style data store declarations (DD-CAP-07, spec AD-04)" - "Updated DD-CAP-03: data_requirements replaces deferred data_bindings" - "Supports organizer-only capabilities bypassing M8 serial chain" - version: "0.2.0" date: "2026-04-07" author: "claude" summary: "Add distribution, submission, and review fields for Library & approval pipeline" changes: - "Added distribution{} for Library listing metadata (GAP-22)" - "Added submission_status enum for submission lifecycle" - "Added review{} for admin approval metadata" - "Revised DD-CAP-03: distribution now ships in v1 (was deferred)" - "Supports E2E flow: author → submit → review → publish → Library → install" - version: "0.1.0" date: "2026-04-07" author: "claude" summary: "Initial Platform Capability schema for Capabilities v1" changes: - "Created for M32 — Capabilities v1: Reference Capabilities (#1223)" - "Resolves GAP-01 (manifest schema) and GAP-02 (naming collision)" - "Minimal v1 fields: skills, required_permissions, runtime, lifecycle, a2a, atoms" - "Addresses GAP-04 (runtime), GAP-05 (lifecycle), GAP-06 (extension_points)" - "DD-CAP-01 through DD-CAP-05 established" # ============================================================================= # SPECIFICATION CONTENT # ============================================================================= spec: status: Draft description: | ## Platform Capability Structure A Platform Capability is a Layer 3 entity that extends document-schema. It adds domain-specific sections for skills, permissions, runtime, lifecycle, and composition. ### Architecture Pattern ``` platform-capability-schema.kno (source of truth) ┌──────────┼──────────────┐ │ │ │ ▼ ▼ ▼ agent.json MCP tools Library listing (derived) (derived) (derived) ├─ contains → role definitions ├─ references → permission tuples (capability-schema) ├─ references → setup workflow (workflow-schema) └─ references → setup guide (guide-schema) ``` ### Naming Convention The entity type is `platform-capability` to distinguish from: - `capability` — permission tuples in `capability-schema.kno` - The colloquial use of "capability" in A2A protocol (`capabilities{}`) # =========================================================================== # SCHEMA DEFINITION # =========================================================================== schema: type: object required: - id - slug - type - version - title - purpose - skills - lifecycle properties: # ----------------------------------------------------------------------- # BASIC TIER (inherited from kno-spec) # ----------------------------------------------------------------------- $schema: type: string const: "platform-capability@2.0.0" description: "Schema declaration" id: type: string format: ulid description: "Unique identifier (ULID). Immutable birth identity." examples: - "01KP3H7VN4QXBCWT9YK8JFME2A" # pragma: allowlist secret slug: type: string format: kebab-case description: "Human-readable identifier for URLs and references. Mutable." examples: - "auth-realm" - "analytics-dashboard" - "white-label-saas" type: type: string const: "platform-capability" description: "Entity type — always 'platform-capability'" version: type: string format: semver description: "Capability version (semver)" examples: - "0.1.0" - "1.0.0" # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: capability_type (discriminator) # Determines whether the platform provisions internal atoms or proxies # to an external A2A endpoint. Drives data sovereignty boundary: # internal → platform stores everything (Tier 2+3) # external → platform stores metadata only (Tier 1) # See: decision-data-sovereignty.md, spec-a2a-adapter-contract.md § 3.4 # ----------------------------------------------------------------------- capability_type: type: string description: | Discriminator for internal vs external capabilities. - `internal`: Platform provisions atoms, runs workflows, stores all data. - `external`: Platform proxies to an external A2A endpoint. The platform stores only metadata (Tier 1: identity, schema ref, relationship graph); message content and artifacts are pass-through only. Defaults to `internal` for backward compatibility with existing capabilities. enum: - internal - external default: internal # PL-009 B (#1825): Provider-Opacity scope. Distinct from capability_type # (which is data-sovereignty). When `platform-internal`, the file is # exempt from the provider-opacity lint because admin/internal prose # legitimately references platform vendors; tenant projections use the # `tenant_description` field which is opacity-enforced separately. opacity_scope: type: string description: | Provider-Opacity scope. Use `platform-internal` for capabilities that ARE the platform's integration of an internal vendor (e.g., auth-realm, storage-bucket). Tenant-facing surfaces project from `tenant_description` and remain Provider-Opacity compliant. enum: - platform-internal - tenant-facing default: tenant-facing # ----------------------------------------------------------------------- # STANDARD TIER (inherited from document-schema) # ----------------------------------------------------------------------- title: type: string description: "Human-readable display name" examples: - "Auth Realm Capability" - "Analytics Dashboard" - "White-Label SaaS Backend" purpose: type: string description: "What this Capability does and why it exists" # PL-007 (#1825): tenant-facing description used for any external/tenant # surface (MCP tools/list, A2A Agent Card, Library catalog). When present, # transformers MUST prefer this over `purpose` for tenant projections. # `purpose` remains the admin/internal source of truth and may reference # platform-internal vendor names. Provider Opacity policy applies to # `tenant_description` only. See content/knowledge-base/provider-opacity.kno. tenant_description: type: string description: | Tenant-facing description for external protocol surfaces (MCP, A2A, Library). Must follow Provider Opacity vocabulary (no vendor names). When omitted, transformers fall back to `purpose`. # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: skills[] # What this Capability offers — maps to A2A skills and MCP tools # ----------------------------------------------------------------------- skills: type: array description: | What the Capability can do. Each skill is an invokable action. Skills are projected to both A2A Agent Card `skills[]` and MCP tool registrations via thin transformations (P10). minItems: 1 items: type: object required: - id - name properties: id: type: string description: "Unique identifier within this Capability" examples: - "provision-realm" - "configure-smtp" name: type: string description: "Human-readable skill name" examples: - "Provision Realm" - "Configure SMTP" description: type: string description: "What the skill does (CommonMark supported)" # PL-007 (#1825): tenant-facing skill description (Provider Opacity # compliant). Preferred by MCP tool registrations and A2A skill # projections. Falls back to `description` when omitted. tenant_description: type: string description: | Tenant-facing skill description for MCP/A2A surfaces. Must follow Provider Opacity vocabulary. When omitted, transformers fall back to `description`. tags: type: array items: type: string description: "Keywords for discoverability" input_modes: type: array items: type: string description: "Accepted MIME types (defaults to text/plain)" default: [ "text/plain" ] output_modes: type: array items: type: string description: "Produced MIME types (defaults to text/plain)" default: [ "text/plain" ] # PL-008 (#1826): handler-endpoint discoverability. Tells the # cap_* MCP discovery tool exactly where to point an agent for # invocation. Strict-mode lint requires one of {rest, mcp_tool, # discovery_only} to be present. invocation: type: object description: | Declares how this skill is invoked. Surfaced verbatim by the `cap__` MCP discovery tool so agents can navigate from a skill name to a real handler endpoint without guessing. Exactly one of `rest`, `mcp_tool`, or `discovery_only` should be set; if multiple are set, `mcp_tool` wins (canonical invocation), then `rest`, then `discovery_only`. properties: rest: type: object description: "REST endpoint that implements this skill." required: - method - path properties: method: type: string enum: [ "GET", "POST", "PUT", "PATCH", "DELETE" ] path: type: string description: | Endpoint path (may include path parameters in `{param}` form). Should match the path declared in the corresponding API .kno entity. examples: - "/admin/auth/connectors/email/configure" - "/admin/realms/{possibility_id}/branding" mcp_tool: type: string description: | Name of the MCP tool that invokes this skill (e.g., a tool generated from an API .kno entity with `mcp.expose: true`). The cap_* discovery tool returns this name so agents can call the underlying tool directly. examples: - "auth_post_admin_auth_connectors_email_configure" discovery_only: type: boolean description: | Explicit marker that this skill has no programmatic invocation surface (e.g., browser-based UX, manual operator action). When true, `reason` SHOULD be set. reason: type: string description: | Human-readable explanation when `discovery_only: true`, so agents understand why no endpoint exists. # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: required_permissions[] # What permissions are needed — uses capability-schema vocabulary # Resolves GAP-02: uses `required_permissions` not `capabilities` # ----------------------------------------------------------------------- required_permissions: type: array description: | Permission tuples needed to install and operate this Capability. Uses `capability-schema.kno` vocabulary: {action, resource, constraints}. Rendered as a human-readable consent screen at installation time. items: type: object required: - action - resource properties: action: type: string description: "The action (from capability-schema vocabulary)" examples: - "provision" - "manage" - "read" - "create" resource: type: string description: "What the action applies to" examples: - "services" - "secrets" - "content" - "members" constraints: type: object description: "Scoping constraints" properties: scope: type: string description: "Permission scope" examples: - "own" - "assigned" - "possibility" description: type: string description: "Human-readable explanation shown in consent UI" examples: - "Create and manage a Keycloak realm for authentication" # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: authorization_details[] # OAuth 2.1 Rich Authorization Requests (RFC 9396) format # Maps required_permissions into structured RAR objects for token scoping # ----------------------------------------------------------------------- authorization_details: type: array description: | OAuth 2.1 Rich Authorization Requests (RFC 9396) objects that express the same permissions as `required_permissions` in a structured format suitable for token-scoped access control. Each object declares a type, actions, locations, and datatypes that map 1:1 to the flat permission tuples. Used by the consent UI and by the auth subsystem when minting scoped tokens. items: type: object required: - type - actions properties: type: type: string description: "RAR type identifier (always 'pspace:capability' for Platform Capabilities)" examples: - "pspace:capability" capability: type: string description: "The capability slug this authorization applies to" actions: type: array description: "Authorized actions (maps to required_permissions[].action)" items: type: string examples: - [ "provision", "configure", "read" ] locations: type: array description: "Resource URIs the actions apply to (XRI patterns)" items: type: string examples: - [ "pspace://realm/{possibility_id}" ] datatypes: type: array description: "Data types the actions operate on" items: type: string examples: - [ "realm-config", "oidc-client" ] # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: atoms[] # Platform building blocks this Capability provisions # ----------------------------------------------------------------------- atoms: type: array description: | Platform building blocks that this Capability provisions during installation. Each atom is a concrete platform resource (realm, bucket, domain, email sender, etc.). Atoms are provisioned in order during installation and cleaned up in reverse order during uninstallation. items: type: object required: - id - type - name properties: id: type: string description: "Unique identifier within this Capability" examples: - "auth-realm" - "storage-bucket" type: type: string description: "Atom type — what platform resource this provisions" examples: - "identity" - "blob-storage" - "secret-store" - "custom-domain" - "email-sender" - "dns-record" - "data-store" - "generic" name: type: string description: "Human-readable name" description: type: string description: "What this atom does" config: type: object description: | Type-specific configuration. Structure depends on `type`. Validated by the executor at installation time. depends_on: type: array items: type: string description: "IDs of atoms that must be provisioned first" state_after: type: object description: | Assertions to verify after provisioning. The executor checks these to confirm the atom was created successfully. properties: assertions: type: array items: type: object properties: check: type: string description: "What to verify" expected: type: string description: "Expected result" # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: runtime{} # How this Capability renders — A2UI vs MCP Apps (GAP-04) # ----------------------------------------------------------------------- runtime: type: object description: | Rendering configuration. Declares which runtime path the Capability uses and provides surface definitions for that path. properties: primary: type: string description: "Primary rendering path" enum: - a2ui - mcp-apps - both - headless default: a2ui fallback: type: string description: "Fallback for non-UI hosts (graceful degradation)" default: text a2ui: type: object description: "A2UI surface definitions (when primary is a2ui or both)" properties: catalog: type: string description: "Which A2UI component catalog to render against" default: possibility surfaces: type: array description: "Declared A2UI rendering surfaces" items: type: object required: - id - type properties: id: type: string description: "Surface identifier" type: type: string description: "A2UI component type" examples: - "card-grid" - "form" - "status-panel" - "data-table" description: type: string description: "What this surface displays" mcp_apps: type: object description: "MCP Apps resource definitions (when primary is mcp-apps or both)" properties: resources: type: array description: "HTML/JS resources served in sandboxed iframes" items: type: object required: - uri properties: uri: type: string description: "Resource URI" examples: - "ui://auth-realm/settings" description: type: string csp: type: object description: "Content Security Policy for this resource" properties: allowed_domains: type: array items: type: string sandbox: type: array items: type: string examples: - [ "allow-scripts", "allow-forms" ] host_context: type: object description: "Host integration settings" properties: theme_variables: type: boolean description: "Whether to receive CSS variables from host" default: true responsive: type: boolean default: true # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: lifecycle{} # Installation and management lifecycle (GAP-05) # ----------------------------------------------------------------------- lifecycle: type: object required: - states description: | Lifecycle state machine for installation, activation, and removal. States follow a strict progression with defined transitions. ``` discovered → installing → installed → active → disabled → uninstalling → uninstalled │ │ │ │ │ └──── upgrading ───┘ │ │ │ │ └───────── failed ◄─────┴────────────────────┘ ``` properties: states: type: array description: "Valid lifecycle states for this Capability" default: - discovered - installing - installed - active - disabled - upgrading - uninstalling - uninstalled - failed items: type: string setup_workflow: type: string format: xri description: | XRI to the workflow-schema instance that describes the installation steps. The CapabilityAgentExecutor reads this workflow to orchestrate installation. examples: - "kno://workflows/auth-realm-setup" cleanup_workflow: type: string format: xri description: | XRI to the workflow that handles uninstallation and cleanup. Atoms are de-provisioned in reverse order. examples: - "kno://workflows/auth-realm-cleanup" auto_activate: type: boolean description: "Activate immediately after successful installation" default: true requires_approval: type: boolean description: | When true, an installation request lands in `approval_required` and MUST be approved by an authorized approver on the installing possibility before the executor begins atom provisioning. When false (default), the orchestrator fast-paths `requested → installing` automatically. Read by the capability-installation orchestrator (#2414) at `request_install` time. Capability publishers set this on capabilities that touch billing, sensitive scopes, or other resources where installer ≠ approver SoD is required. default: false history_policy: type: object description: | Policy for version history tracking (P9 Temporal). Designed in v1; TerminusDB integration implemented in v2 (DD-CAP-05). properties: retention: type: string description: "How much history to retain" enum: - full - recent - none default: full recent_count: type: integer description: "Number of recent versions to embed (when retention is recent)" default: 10 # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: a2a{} # A2A protocol metadata for Agent Card derivation # Resolves GAP-02: uses `protocol_capabilities` not `capabilities` # # AGENT CARD ↔ .kno CONSISTENCY RULES (adapter contract § 3.5): # These 6 fields MUST be consistent between the .kno entity and # the Agent Card served at /.well-known/agent.json: # 1. Agent Card `name` ↔ .kno `title` (MUST match) # 2. Agent Card `description` ↔ .kno `description` (SHOULD match) # 3. Agent Card `version` ↔ .kno `version` (MUST match) # 4. Agent Card `skills[*].id` ↔ .kno `skills[*].id` (MUST match) # 5. Agent Card `url` ↔ .kno `a2a.endpoint_url` (MUST match) # 6. Agent Card `capabilities.streaming` ↔ .kno `a2a.protocol_capabilities.streaming` (MUST match) # Drift detected during 300s Agent Card re-fetch triggers trust score penalty. # ----------------------------------------------------------------------- a2a: type: object description: | A2A protocol metadata. Used to derive the Agent Card (P10). Field naming deliberately avoids the `capabilities` collision: uses `protocol_capabilities` for A2A protocol features. For external capabilities (`capability_type: external`), the `endpoint_url` is the external provider's A2A endpoint. The platform proxies requests to this URL and does not store message content (data sovereignty: pass-through only). properties: endpoint_url: type: string format: uri description: | A2A endpoint URL for this Capability's agent. For internal capabilities: points to the platform's own A2A handler. For external capabilities: points to the external provider's A2A endpoint. MUST use HTTPS with valid TLS certificate. examples: - "https://api.possibility.space/a2a/auth/v1" - "https://grantfinder.example.com/a2a" protocol_capabilities: type: object description: | A2A protocol features supported. Maps to agent-card-schema `capabilities{}` field in the derived Agent Card. Named `protocol_capabilities` to avoid GAP-02 collision. properties: streaming: type: boolean default: false push_notifications: type: boolean default: false state_transition_history: type: boolean default: false authentication: type: object description: "Auth requirements for the A2A endpoint" properties: schemes: type: array items: type: string examples: - [ "Bearer" ] credentials: type: string description: "Non-secret scheme config (e.g., tokenUrl). MUST NOT contain secrets." # ----------------------------------------------------------------- # External capability fields (capability_type: external) # Added in v0.8.0 for #1363 (Brownfield E2E — External Capabilities) # ----------------------------------------------------------------- adapter_version: type: string format: semver description: | Version of the pspace A2A adapter the external provider implements. Maps to Agent Card `metadata.pspace_adapter_version`. Used for protocol compatibility checking during submission validation. examples: - "1.0.0" health_check_url: type: string format: uri description: | Health probe endpoint for external capabilities. The platform sends GET requests every 60s to monitor availability. Defaults to `{origin of endpoint_url}/health` if not specified. MUST return 200 OK when healthy. examples: - "https://grantfinder.example.com/health" service_token_ref: type: string description: | OpenBao secret path where the service token for this external capability installation is stored. Format: `secret/data/pspace/{possibility_slug}/capabilities/{capability_slug}/service-token` Set by the platform during installation; not set by the publisher. MUST NOT contain the actual token value — this is a reference only. examples: - "secret/data/pspace/acme-corp/capabilities/grant-finder/service\ -token" circuit_breaker_config: type: object description: | Circuit breaker configuration for external capability health monitoring. Controls when the platform stops routing requests to an unhealthy external endpoint. See adapter contract § 10.3-10.4 for defaults and trust score impact. properties: failure_threshold: type: number description: | Failure rate percentage (0-100) over the evaluation window that triggers circuit breaker open state. Default: 50%. default: 50 minimum: 0 maximum: 100 recovery_timeout_seconds: type: integer description: | Seconds to wait in open state before transitioning to half-open for a test probe. Default: 30s. default: 30 minimum: 5 check_interval_seconds: type: integer description: | Seconds between health probes. Default: 60s. Agent Card re-fetch interval is fixed at 300s. default: 60 minimum: 10 evaluation_window_seconds: type: integer description: | Time window in seconds over which failure rate is calculated. Default: 300s (5 minutes). default: 300 minimum: 60 # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: extension_points[] (GAP-06) # Where this Capability integrates into the host platform # ----------------------------------------------------------------------- extension_points: type: array description: | Host integration points — UI slots, API routes, and dashboard sections that this Capability populates. Follows the Shopify extension-point model (DP5 from landscape analysis). items: type: object required: - slot properties: slot: type: string description: "Host slot identifier" examples: - "dashboard.sidebar" - "admin.settings.auth" - "api.routes" component: type: string format: xri description: "Fragment XRI to the surface or tool providing this slot" examples: - "#surfaces/settings-panel" priority: type: integer description: "Rendering priority (lower = earlier)" default: 50 routes: type: array description: "API routes (when slot is api.routes)" items: type: object properties: method: type: string enum: [ GET, POST, PUT, DELETE, PATCH ] path: type: string handler: type: string format: xri # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: provider{} # Who publishes this Capability # ----------------------------------------------------------------------- provider: type: object description: "Organization or entity providing this Capability" properties: organization: type: string description: "Provider name" examples: - "Possibility" url: type: string format: uri description: "Provider URL" verified: type: boolean description: "Whether the provider is verified by the platform" default: false # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: distribution{} # Library listing metadata (GAP-22) # ----------------------------------------------------------------------- distribution: type: object description: | Metadata for Library listing and discovery. Controls how the Capability appears when browsing or searching the Library. NOTE: As of schema 2.0.0, primary classification (`category`, singular) and search tags (`tags`, plural) moved to top-level `categories[]` (closed enum, max 5) and `keywords[]` (open, max 12). The `distribution{}` block now only carries presentation metadata (description, screenshots, icon). properties: listing_description: type: string description: | Short description for Library card view (≤200 chars). Falls back to `purpose` if omitted. screenshots: type: array description: "Screenshot URLs for the detail view" items: type: object properties: url: type: string format: uri caption: type: string icon: type: string description: "Icon identifier for Library card (Lucide icon name)" examples: - "shield" - "bar-chart" - "mail" # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: compatibility{} # Platform version compatibility + deprecation signalling. # Introduced in 1.4.0 (Capabilities v2 Phase 1, #1833; renumbered from 1.2.0 during M33→main merge). # ----------------------------------------------------------------------- compatibility: type: object description: | Declares platform version range and deprecation state. Consumed by the Install gate (compatibility pre-check) and the Library backend (deprecation badge + filter). properties: requires_pspace_version: type: string description: | node-semver range string. Install gate rejects with a compat error if the current platform version does not satisfy. examples: - "^1.0.0" - ">=2.0.0" - ">=1.5.0 <3.0.0" deprecated: type: boolean default: false description: "True once the Capability is marked deprecated" deprecation_notice: type: string description: "Human-readable deprecation message (CommonMark supported)" deprecated_from: type: string format: semver description: "Capability version from which deprecation applies" end_of_life: type: string format: date description: "YYYY-MM-DD after which no further updates will ship" # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: categories[] # Top-level closed-enum classification for Library browse/filter. # As of schema 2.0.0, this is the ONLY classification field; the # legacy `distribution.category` (singular) was removed. # Introduced in 1.4.0 (renumbered from 1.2.0 during M33→main merge); legacy form retired in 2.0.0. # ----------------------------------------------------------------------- categories: type: array maxItems: 5 description: | Closed-enum categories. Drives Library browse + filter UX. A Capability may belong to multiple categories (e.g. a capability providing both identity + CMS). As of schema 2.0.0, this is the ONLY classification field; populate it explicitly. The legacy `distribution.category` (singular, free-form) was removed. items: type: string enum: - ai - analytics - authentication - authorization - cms - commerce - communication - developer-tools - identity - integration - messaging - monitoring - search - security - storage - workflow examples: - [ "authentication", "identity" ] - [ "storage" ] # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: keywords[] # Open free-form keywords (max 12) for fine-grained search. # Complements categories[] (closed enum) / supersedes distribution.tags. # Introduced in 1.4.0 (Capabilities v2 Phase 1, #1833; renumbered from 1.2.0 during M33→main merge). # ----------------------------------------------------------------------- keywords: type: array maxItems: 12 description: | Open-ended searchable keywords. Complements `categories[]` for fine-grained discovery. Max 12 entries — keep focused. items: type: string examples: - [ "sso", "oidc", "keycloak", "login" ] - [ "minio", "s3-compatible", "object-storage" ] # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: publisher{} # Publisher identity + trust tier. Drives Library trust signalling. # Introduced in 1.4.0 (Capabilities v2 Phase 1, #1833; renumbered from 1.2.0 during M33→main merge). # Three-tier model per #1137 registry research. # ----------------------------------------------------------------------- publisher: type: object required: - id - tier description: | Publisher metadata. Three tiers control UX trust signalling and write-path capabilities: - `platform` auto-verified at publish time (repo commit path = proof) - `verified` requires a signed publisher key (gated on Auth 7) - `community` is self-declared; no signature verification properties: id: type: string description: | Publisher identifier. For `platform` tier: ULID or the canonical slug `possibility-space`. For `verified` / `community` tiers: ULID referencing a publisher entity. examples: - "possibility-space" - "01KP4GXWMR8NVJQY5ZH2B6KFDT" # pragma: allowlist secret tier: type: string enum: - platform - verified - community description: "Trust tier — see block description for semantics" # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: featured # Editorial promotion flag for Library homepage + featured collections. # Introduced in 1.4.0 (Capabilities v2 Phase 1, #1833; renumbered from 1.2.0 during M33→main merge). # ----------------------------------------------------------------------- featured: type: boolean default: false description: | Editorial featured flag — surfaces the Capability on Library homepage and in curated collections. Set by `platform` publishers only; `verified` and `community` publishers cannot self-feature. # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: provenance{} # Capability authorship attestation. Introduced in 2.2.0 (M55 #2406). # The schema layer treats every subfield as OPTIONAL so this is an # additive change. The submission-pipeline validator # (`capability-submission-validator.ts`) treats # `provenance.publisher_possibility_xri` as REQUIRED at # `submission_status: submitted` and beyond. The commit-time lint # (`scripts/lint-capability-provenance.ts`) enforces it on every # `content/capabilities/*.kno` file checked into the repo. # # Append-only enforcement of `contributors[]` and `version_history[]` # is the orchestrator's responsibility (#2413). `signature_jwt` values # are signed with the per-tenant key issued by #2409 (out of scope # here; the schema only declares the shape). # ----------------------------------------------------------------------- provenance: type: object description: | Capability authorship attestation. Declares which Possibility published this capability, which users contributed across versions, and the version history of the manifest itself. The orchestrator (#2413) enforces append-only semantics on `contributors[]` and `version_history[]` — entries can be added on each submission but never modified or removed in place. properties: publisher_possibility_xri: type: string description: | XRI of the Possibility that published this capability. REQUIRED at `submission_status: submitted` and beyond (enforced by `capability-submission-validator.ts`) and on every committed `content/capabilities/*.kno` file (enforced by `scripts/lint-capability-provenance.ts`). OPTIONAL at the schema layer to keep this property additive. Format per RFC-013 (Identity Separation): - Identity XRI: `pspace://possibility/` - Named XRI: `pspace://possibility:` Identity XRIs are preferred for long-lived references (slugs are mutable; ULIDs are not). pattern: "^pspace://possibility[/:][a-zA-Z0-9_-]+$" examples: - "pspace://possibility/01KP3GXWMR8NVJQY5ZH2B6KFDT" - "pspace://possibility:possibility-foundry" contributors: type: array description: | Append-only list of users who contributed to this capability. Each entry attests that a specific user (acting in a specific role on behalf of a specific Possibility) participated at a specific time. The orchestrator (#2413) rejects any submission that mutates or removes pre-existing entries. items: type: object required: - user_xri - possibility_xri - role - at properties: user_xri: type: string description: "Identity XRI of the contributing user." pattern: "^pspace://user[/:][a-zA-Z0-9_-]+$" possibility_xri: type: string description: | Identity XRI of the Possibility the user was acting on behalf of. Often equal to `provenance.publisher_possibility_xri`, but a contributor MAY act for a different (authorized) tenant when the publishing Possibility delegates review or co-authorship. pattern: "^pspace://possibility[/:][a-zA-Z0-9_-]+$" role: type: string enum: - author - reviewer - approver description: "Role this contributor played for this entry." at: type: string format: date-time description: "ISO8601 timestamp of the contribution." signature_jwt: type: string description: | Optional JWT signature attesting to this contribution. Signed with the per-tenant key issued by #2409. Until #2409 ships, validators treat this as opaque. version_history: type: array description: | Append-only list of manifest versions. Provides an inline, minimal version trail for the capability manifest. Full VCS backing remains TerminusDB per Capabilities v2 deferral. items: type: object required: - version - at - author_user_xri properties: version: type: string description: "Semver version of the capability manifest." pattern: "^[0-9]+\\.[0-9]+\\.[0-9]+(-[0-9A-Za-z.-]+)?(\\+[0-9A-Za-z.-]+)?$" at: type: string format: date-time description: "ISO8601 timestamp this version was published." author_user_xri: type: string description: "Identity XRI of the user who authored this version." pattern: "^pspace://user[/:][a-zA-Z0-9_-]+$" change_summary: type: string description: "Short human-readable summary of changes." signature_jwt: type: string description: | Optional JWT signature attesting to this version publish. Signed with the per-tenant key issued by #2409. # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: submission_status # Submission lifecycle for the approval pipeline # ----------------------------------------------------------------------- submission_status: type: string description: | Tracks the Capability's position in the submission → review → publish pipeline. Only Capabilities with status `published` appear in the Library for installation. enum: - draft - submitted - in_review - revisions_requested - approved - published - rejected - withdrawn default: draft # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: review{} # Admin review metadata for the approval queue # ----------------------------------------------------------------------- review: type: object description: | Review metadata populated during the admin approval process. Empty until first submission; updated by admin reviewers. properties: reviewer_id: type: string format: ulid description: "ULID of the admin who reviewed" reviewed_at: type: string format: date-time description: "Timestamp of the review decision" decision: type: string enum: - approved - rejected - revisions_requested description: | The review decision. Three outcomes: - approved: Capability passes review, eligible for publishing - rejected: Capability does not meet standards - revisions_requested: Reviewer requests changes before re-review comments: type: string description: | Free-text comments from the reviewer. Visible to the publisher for both approvals and rejections. submitted_at: type: string format: date-time description: "Timestamp when the publisher submitted for review" submitted_by: type: string format: ulid description: "ULID of the user who submitted" # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: auth_context{} # Two-Context Auth Model — see spec AD-01 / AD-02, DD-CAP-06 # ----------------------------------------------------------------------- auth_context: type: object description: | Declares authentication requirements using the Two-Context Auth Model. Organizer Auth (platform Keycloak) vs End-User Auth (per-Possibility realm, blocked by M8). Most capabilities only need organizer auth. properties: organizer_auth: type: string description: | Whether the organizer (Possibility owner) must authenticate to install/configure this capability. Almost always `required`. enum: - required - optional - none default: required end_user_auth: type: string description: | Whether end-users of the Possibility need to authenticate to use this capability. Only `required` for auth-facing capabilities (Login with Possibility, Member Area, SSO). Capabilities with `required` are gated by M8 completion. enum: - required - optional - none default: none depends_on_capability: type: string format: xri pattern: "^pspace://capability/[a-z][a-z0-9-]*$" description: | Canonical XRI reference to the capability this depends on. Form: `pspace://capability/{slug}` (singular `capability`, slug is lowercase-dash). Bare slugs are not accepted. Aliases are not resolved. The validator, runtime, and drift-guard all require this exact form. See `docs/architecture/capability-dependency-identity.md`. Only relevant when `end_user_auth` is `required` or `optional`. examples: - "pspace://capability/auth-realm" - "pspace://capability/login-with-possibility" # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: data_requirements[] # PDS-style data store declarations — see spec AD-04, DD-CAP-07 # ----------------------------------------------------------------------- data_requirements: type: array description: | Declares the data stores and connectors this Capability needs. Follows the ATProto PDS model: capabilities declare data needs, the platform resolves storage. v1: provider is always `possibility.space`. v2+: supports external/self-hosted providers. items: type: object required: - id - type properties: id: type: string description: "Unique identifier within this Capability's requirements" examples: - "task-store" - "github-connector" type: type: string description: "Kind of data requirement" enum: - data-store - connector schema_xri: type: string format: xri description: | XRI to the schema defining the data shape. Used for validation and data migration planning. examples: - "kno://schemas/task-object" - "kno://schemas/analytics-event" connector_xri: type: string format: xri description: | XRI to the connector definition. Only for type: connector. The referenced connector must be configured before install. examples: - "kno://connectors/github" - "kno://connectors/stripe" provider: type: string description: | Where this data lives. v1: always `possibility.space`. v2+: supports external providers via XRI resolution. default: "possibility.space" required: type: boolean description: "Whether this data requirement must be satisfied for installation" default: true description: type: string description: "Human-readable description of what this data is for" # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: runtime_requirements{} # Platform compatibility constraints — see #1332 # ----------------------------------------------------------------------- runtime_requirements: type: object description: | Declares platform version and service compatibility constraints. The validator checks these against `PLATFORM_RUNTIME` to ensure the capability can run on the current platform version. Returns structural errors (blocks submission) if incompatible. properties: platform_api: type: string description: | Minimum platform API version required (semver constraint). Checked against PLATFORM_RUNTIME.platform_api using >=X.Y.Z comparison. examples: - ">=0.5.0" - ">=0.6.0" services: type: array description: | Platform services this Capability requires. All listed services must be available in PLATFORM_RUNTIME.services. items: type: string examples: - [ "keycloak", "minio", "openbao" ] - [ "postgres", "stalwart" ] node: type: string description: | Minimum Node.js version constraint (semver format). Checked against the platform's installed Node.js major version during submission validation. examples: - ">=20" - ">=22" # ----------------------------------------------------------------------- # DOMAIN-SPECIFIC: publisher_verification_status # Domain verification status for the publisher — see #1329 # ----------------------------------------------------------------------- publisher_verification_status: type: string description: | Reflects whether the publisher's domain has been verified via DNS TXT record (see capabilities-publisher-verification-api). Set by the platform during the submission pipeline; not set by the publisher directly. Used by the validator for domain cross-check warnings (#1330). enum: - unverified - pending - verified default: unverified # ============================================================================= # EXAMPLES # ============================================================================= examples: - title: "Internal Platform Capability (single-atom)" description: "Internal capability — platform provisions atoms, A2UI rendering" content: | $schema: platform-capability@2.0.0 id: 01KP3H7VN4QXBCWT9YK8JFME2A slug: login-with-possibility type: platform-capability version: 0.1.0 capability_type: internal title: "Login with Possibility" purpose: | Provisions a dedicated Keycloak realm for per-Possibility authentication, including OIDC discovery, branding, and SMTP. Follows the "Login with Google" / "Login with GitHub" pattern. skills: - id: provision-realm name: Provision Realm description: "Create and configure a pspace-{slug} Keycloak realm" tags: [auth, provisioning, keycloak] - id: configure-smtp name: Configure SMTP description: "Set up per-realm email sender configuration" tags: [auth, email, smtp] required_permissions: - action: provision resource: services constraints: scope: own description: "Create a Keycloak realm for this Possibility" - action: manage resource: secrets constraints: scope: own description: "Store realm credentials in secrets manager" atoms: - id: auth-realm type: identity name: "Keycloak Realm" description: "Dedicated authentication realm" state_after: assertions: - check: "realm_exists" expected: "true" - check: "oidc_discovery_url_responds" expected: "200" runtime: primary: a2ui fallback: text a2ui: catalog: possibility surfaces: - id: settings-panel type: form description: "Realm configuration form" lifecycle: states: - discovered - installing - installed - active - disabled - uninstalling - uninstalled - failed setup_workflow: "kno://workflows/auth-realm-setup" cleanup_workflow: "kno://workflows/auth-realm-cleanup" auto_activate: true history_policy: retention: full a2a: endpoint_url: "https://api.possibility.space/a2a/auth/v1" protocol_capabilities: streaming: true push_notifications: false state_transition_history: true authentication: schemes: [Bearer] auth_context: organizer_auth: required end_user_auth: required depends_on_capability: null # This IS the auth capability data_requirements: - id: realm-config type: data-store schema_xri: "kno://schemas/identity-config" provider: "possibility.space" description: "Realm configuration data (branding, SMTP, clients)" provider: organization: Possibility url: "https://possibility.space" verified: true - title: "External Platform Capability (brownfield A2A)" description: | External capability — platform proxies to an external A2A endpoint. No atoms provisioned; data sovereignty is pass-through (Tier 1 only). Demonstrates the Brownfield E2E scenario (Devon's GrantSpark). content: | $schema: platform-capability@2.0.0 id: 01KR7BNXP5MQWT3Y8ZK4JFHE9C slug: grant-finder type: platform-capability version: 1.0.0 capability_type: external title: "GrantSpark Grant Finder" purpose: | AI-powered grant discovery and application assistance. Searches federal and state grant databases, matches eligibility criteria, and drafts application narratives. skills: - id: search-grants name: Search Grants description: "Search federal and state grant databases by eligibility criteria" tags: [grants, search, ai] - id: draft-narrative name: Draft Narrative description: "Generate grant application narrative sections" tags: [grants, writing, ai] required_permissions: - action: read resource: content constraints: scope: own description: "Read possibility profile for grant matching" # No atoms[] — external capabilities do not provision platform resources runtime: primary: a2ui fallback: text lifecycle: states: - discovered - installing - installed - active - disabled - uninstalling - uninstalled - failed auto_activate: true history_policy: retention: recent recent_count: 5 a2a: endpoint_url: "https://grantfinder.example.com/a2a" protocol_capabilities: streaming: true push_notifications: false state_transition_history: false authentication: schemes: [Bearer] adapter_version: "1.0.0" health_check_url: "https://grantfinder.example.com/health" circuit_breaker_config: failure_threshold: 50 recovery_timeout_seconds: 30 check_interval_seconds: 60 evaluation_window_seconds: 300 provider: organization: GrantSpark Inc. url: "https://grantfinder.example.com" verified: true