diff --git a/specs/fenestra/ADVERSARIAL-REVIEWS.md b/specs/fenestra/ADVERSARIAL-REVIEWS.md
new file mode 100644
index 0000000..72f0815
--- /dev/null
+++ b/specs/fenestra/ADVERSARIAL-REVIEWS.md
@@ -0,0 +1,545 @@
+# Fenestra v0.1.0 Adversarial Reviews
+
+Generated: 2025-12-27
+
+These reviews were conducted by adversarial agents to identify gaps, inconsistencies, and areas for improvement in the Fenestra specification before OAI submission.
+
+---
+
+## Table of Contents
+
+1. [Spec Consistency Review](#1-spec-consistency-review)
+2. [Platform Implementer Review](#2-platform-implementer-review)
+3. [Developer Experience Review](#3-developer-experience-review)
+4. [Security & Governance Review](#4-security--governance-review)
+5. [Synthesis & Recommendations](#5-synthesis--recommendations)
+
+---
+
+## 1. Spec Consistency Review
+
+**Perspective:** Standards body reviewer checking for internal consistency, OAI format compliance, and ambiguities.
+
+### CRITICAL ISSUES (must fix before submission)
+
+#### 1.1 Broken Schema Architecture: Inline vs Referenced Objects
+
+**Location**: Throughout spec, particularly Extension Point configuration objects
+
+**Problem**: The prose defines ~40+ discrete object types (e.g., `ResponseSchemaObject`, `EndpointObject`, `InteractivityObject`, `RuntimeObject`, etc.) with anchor links and separate documentation sections. However, the JSON schema **inlines** these as nested anonymous objects instead of using `$ref` to reusable `$defs` entries.
+
+**Example**:
+- **Prose** (line 678): `schema | [Response Schema Object](#responseSchemaObject) | JSON Schema definition for valid responses.`
+- **Schema** (line 773-791): Defines `schema` as an inline anonymous object, not a `$ref`
+
+**Why This Matters**:
+- OAI specs (OpenAPI, Arazzo) use `$ref` extensively for reusable components
+- Tools cannot validate references to these "objects" that don't exist as `$defs`
+- Inconsistent with OAI specification patterns
+- Makes schema composition and reuse impossible
+
+**Fix Required**: Either:
+1. Extract all prose-documented objects to `$defs` and use `$ref` (RECOMMENDED for OAI submission), OR
+2. Flatten prose to match inline schema structure (removes semantic clarity)
+
+---
+
+#### 1.2 Missing Discriminated Union for `extensionTypeConfig`
+
+**Location**: `/specs/fenestra/versions/0.1.0.md` line 619
+
+**Problem**: Prose says:
+```
+extensionTypeConfig | [JSON Response Config Object] | [Coded Components Config Object] | ...
+ | Configuration specific to the extension type.
+```
+
+This implies a **discriminated union** based on `extensionType` value.
+
+**Schema** (line 715-718) says:
+```json
+"extensionTypeConfig": {
+ "type": "object",
+ "description": "Configuration specific to the extension type. Schema varies based on extensionType value."
+}
+```
+
+This accepts **any object** with no validation!
+
+**Why This Matters**:
+- No validation that `extensionTypeConfig` matches `extensionType`
+- Could pass validation with `extensionType: "iframe"` but `extensionTypeConfig: {sdk: "..."}` (coded components config)
+- Critical for tooling correctness
+
+**Fix Required**: Use JSON Schema conditional validation:
+```json
+"allOf": [
+ {
+ "if": {"properties": {"extensionType": {"const": "jsonResponse"}}},
+ "then": {"properties": {"extensionTypeConfig": {"$ref": "#/$defs/JsonResponseConfig"}}}
+ },
+ // ... repeat for each extensionType
+]
+```
+
+---
+
+#### 1.3 Missing `patternProperties` for Specification Extensions
+
+**Location**: Multiple objects claim to support `x-` extensions but lack schema enforcement
+
+**Objects Missing Pattern Properties**:
+- `DeclarativeSchema` (prose line 1027 says "MAY be extended", schema line 1171 has no `patternProperties`)
+- `I18n` (prose line 1098, schema line 1205)
+- `Compliance` (prose line 1233, schema line 1266)
+- `AgentInteraction` (prose line 1455, schema line 1370)
+
+**Fix Required**: Add to all affected object definitions:
+```json
+"patternProperties": {
+ "^x-": {}
+}
+```
+
+---
+
+#### 1.4 Broken Internal Anchor Links
+
+**Location**: `/specs/fenestra/versions/0.1.0.md` line 110
+
+**Problem**:
+```markdown
+This is the root object of a [Fenestra Description](#fenestraDescription).
+```
+
+But there is NO `` anchor tag anywhere in the document.
+
+**Fix Required**: Add anchors to all Definition sections and ensure references match
+
+---
+
+#### 1.5 Inconsistent Enum Definitions (Prose vs Schema)
+
+**Location**: AgentProtocol `name` field
+
+**Prose** (line 1512):
+```
+name | string | **REQUIRED**. Protocol name. Values include: `mcp`, `openai-functions`,
+ `anthropic-tools`, `langchain-tools`, `custom`.
+```
+
+Note: Says "Values **include**" (not "MUST be one of")
+
+**Schema** (line 1388):
+```json
+"name": { "type": "string" }
+```
+
+No enum constraint at all!
+
+**Fix Required**:
+1. If closed enum: Change prose to "MUST be one of" and add enum to schema
+2. If open enum: Clarify prose to say "MAY include the following well-known values"
+
+---
+
+#### 1.6 Version Pattern Mismatch
+
+**Prose** (line 81): Only mentions `major.minor`, with no discussion of patch versions
+
+**Schema** (line 12): Requires `major.minor.patch` and allows pre-release tags
+
+**Fix Required**: Clarify prose to explicitly state full `major.minor.patch` format
+
+---
+
+### MAJOR ISSUES (should fix)
+
+1. **Inconsistent Terminology**: "Map[X, Y]" in prose vs JSON Schema object+additionalProperties
+2. **Ambiguous RFC 2119 Usage**: "MAY be used by tooling as required" is contradictory
+3. **Missing Schema Hosting Information**: Schema `$id` URI not mentioned in prose
+4. **No Validation for Cross-References**: String identifiers can reference non-existent objects
+5. **Inconsistent Default Value Documentation**: Some inline, some separate
+6. **JSON Schema Draft Version Mismatch**: Prose claims 2020-12, schema uses draft-07
+
+### MINOR ISSUES
+
+1. Example coverage gaps (missing complete examples)
+2. Inconsistent capitalization in enum values
+3. No guidance on multi-document support
+4. Vague external references
+5. No deprecation strategy
+
+---
+
+## 2. Platform Implementer Review
+
+**Perspective:** Platform engineers from HubSpot, Shopify, Salesforce, Slack, Figma evaluating adoption feasibility.
+
+### DEAL BREAKERS
+
+#### 2.1 Cannot Express Multi-Context Architectures
+**Affected platforms:** Figma, VS Code, Electron-based apps, browser extensions
+
+Fenestra assumes a single execution context. Real platforms have:
+- **Figma:** Main thread (plugin logic) + UI thread (rendering) with message passing
+- **VS Code:** Extension host process + webview panel
+- **Browser extensions:** Background worker + content script + popup
+
+The 5 extension types all assume single-context. No mechanism to describe separate execution contexts, message passing protocols, or context-specific API access.
+
+---
+
+#### 2.2 Backend/Serverless Requirements Are Invisible
+**Affected platforms:** HubSpot, Shopify, Salesforce, Slack
+
+Most platforms require backend infrastructure alongside UI:
+- **HubSpot:** Serverless functions required for data manipulation
+- **Shopify:** Webhook endpoints required for event subscriptions
+- **Slack:** HTTP endpoints required for slash commands, interactivity
+
+A developer reading the Fenestra doc would have no idea they need to build a web server.
+
+---
+
+#### 2.3 Hybrid Extension Models Cannot Be Represented
+**Affected platforms:** Shopify, Salesforce, Microsoft Teams
+
+Real platforms use **multiple extension types simultaneously** for a single app:
+
+**Shopify example:**
+- Settings page: iframe
+- Embedded admin app: iframe with App Bridge SDK
+- Checkout UI: Polaris React components
+- App embeds on storefront: Liquid templates + JavaScript
+
+Extension points only support a single `extensionType`. Cannot express these hybrid patterns.
+
+---
+
+#### 2.4 Legacy Framework Support Is Impossible
+**Affected platforms:** Salesforce, SharePoint, Dynamics 365
+
+Enterprise platforms have multiple generations of component systems:
+- **Salesforce:** Visualforce (2008) + Aura (2014) + LWC (2019)
+
+No mechanism to express multiple component systems, migration paths, or feature parity differences.
+
+---
+
+### SIGNIFICANT GAPS
+
+1. **State Management Model Undefined**: Who owns state? Platform or developer?
+2. **Authentication Flows Underspecified**: Only 4 enum values, no token refresh, SSO, etc.
+3. **Build/Deployment Model Missing**: Who hosts? How to deploy?
+4. **Testing/Dev Workflow Invisible**: Local dev, hot reload, test environments
+5. **Rate Limits and Quotas Absent**: Every platform has limits
+6. **Performance Requirements Underspecified**: Bundle size, render time, memory
+7. **Error Handling Undefined**: What happens when things fail?
+8. **Versioning and Breaking Changes**: No compatibility matrix
+
+### AWKWARD FITS
+
+1. App Bridge / Message Passing Systems (calling it "iframe" undersells the pattern)
+2. CSS-Only Component Libraries (not really "SDK exports")
+3. Adaptive Cards / Block Kit connection to declarativeSchemas
+4. CDN-Only SDKs That Aren't Packages
+5. Mobile vs Web SDK Relationship
+6. Theming Scope (only under embeddedSdkConfig, should be platform-level?)
+
+### ADOPTION ESTIMATES
+
+| Platform | Fit | Notes |
+|----------|-----|-------|
+| HubSpot | 75% | Coded components fit well, missing serverless/deploy |
+| Miro | 85% | Optional components model works, missing local dev |
+| Slack | 60% | Block Kit fits, missing state management, webhooks |
+| Shopify | 40% | Hybrid model doesn't fit, App Bridge misrepresented |
+| Salesforce | 25% | Multiple frameworks can't coexist, too complex |
+| Figma | 20% | Multi-context architecture cannot be expressed |
+
+---
+
+## 3. Developer Experience Review
+
+**Perspective:** Tooling developers building IDE plugins, code generators, AI assistants, documentation generators.
+
+### TOOLING BLOCKERS
+
+#### 3.1 Props Schema is Broken for Type Generation
+
+```yaml
+props:
+ onClick:
+ type: function # NOT VALID JSON SCHEMA!
+```
+
+JSON Schema doesn't have a `function` type. TypeScript generators will crash or generate `any`.
+
+---
+
+#### 3.2 Polymorphic extensionTypeConfig is Untyped
+
+```json
+"extensionTypeConfig": {
+ "type": "object" // No discriminator, no oneOf
+}
+```
+
+Type generators create `extensionTypeConfig: any`. No validation of config shape.
+
+---
+
+#### 3.3 SDK Export Metadata is Too Weak
+
+SDK exports only have `type` and `description`. Missing:
+- Import style (named vs default export)
+- Parameters/props schema
+- Return type
+- Whether it needs side-effect imports (CSS)
+
+Code generators can't create proper import statements.
+
+---
+
+#### 3.4 Component Identifier Ambiguity
+
+Components referenced by string keys everywhere:
+- `componentCatalog.components.Button`
+- `supportedComponents: ["Button"]`
+- `sdkBinding.export: "Button"`
+
+Are these guaranteed to match? Case-sensitive? No canonical identifier exists.
+
+---
+
+#### 3.5 Event Payload Schemas are Undefined
+
+```json
+"payload": {
+ "type": "object" // No schema!
+}
+```
+
+Can't generate event handler types. Don't know what data events contain.
+
+---
+
+### USABILITY ISSUES
+
+1. No import path construction rules
+2. Weak typing for string arrays (supportedComponents, context.provides)
+3. Props schema format inconsistency (is it properties section or full schema?)
+4. No composition validation rules (can Button contain Modal?)
+5. `"all"` magic string in supportedComponents
+
+### MISSING INFORMATION
+
+1. No type definition linking (where is ButtonProps interface?)
+2. Component children/slot requirements unclear
+3. No SDK version to component availability matrix
+4. Missing event handler signatures
+5. No context data schemas
+6. Component examples not machine-parseable
+7. No build/bundle requirements
+8. Missing deprecation timeline
+
+### DX IMPROVEMENTS SUGGESTED
+
+1. Add $ref support for component props
+2. Provide machine-readable import examples
+3. Add OpenAPI links for runtime data
+4. Include visual reference data (thumbnails, Storybook links)
+5. Add accessibility testing metadata
+6. Provide component dependency graph
+7. Add performance characteristics
+
+---
+
+## 4. Security & Governance Review
+
+**Perspective:** CISO evaluating whether to approve Fenestra-documented integrations for production use.
+
+### NOTE ON SCOPE
+
+Many security concerns are about **platform implementation**, not the specification itself. The spec is a description format - it cannot enforce security. However, the spec SHOULD:
+1. Provide vocabulary for describing security posture
+2. Document best practices
+3. Include Security Considerations section
+4. Recommend what tooling should validate
+
+### SECURITY VULNERABILITIES
+
+#### 4.1 Agent Permission Model is Coarse-Grained
+
+```yaml
+agentPermissions:
+ canPerformActions: true # Can DELETE EVERYTHING
+```
+
+Boolean flags with no resource-level scoping. An AI agent with `canPerformActions: true` could execute destructive operations.
+
+**Recommendation**: Add granular permission model with resource scoping.
+
+---
+
+#### 4.2 No Authentication Mechanism for Agent Interactions
+
+The specification describes agent protocols but omits:
+- How agents authenticate to platforms
+- Session management
+- Token validation
+- Permission revocation
+
+**Recommendation**: Add authentication section to agentInteraction.
+
+---
+
+#### 4.3 JSON Schema Injection in Declarative Schemas
+
+`schemaUrl` allows arbitrary URI references, enabling:
+- SSRF (Server-Side Request Forgery)
+- Schema poisoning with circular dependencies
+- XSS via documentation URLs
+
+**Recommendation**: Document URL validation requirements in Security Considerations.
+
+---
+
+#### 4.4 CSP and Sandbox Configuration Not Validated
+
+CSP policies are just strings with no validation:
+
+```yaml
+sandboxing:
+ cspPolicy: "default-src *; script-src 'unsafe-inline' 'unsafe-eval' *"
+```
+
+**Recommendation**: Document minimum CSP requirements and what tooling SHOULD validate.
+
+---
+
+#### 4.5 No Subresource Integrity for SDK/CDN References
+
+SDKs loaded from CDN have no integrity checks:
+
+```yaml
+sdks:
+ stripe-js:
+ cdn: https://js.stripe.com/v3/
+ cdnRequired: true
+ # Missing: integrity hash
+```
+
+**Recommendation**: Add optional `integrity` field, document SRI best practices.
+
+---
+
+### COMPLIANCE GAPS
+
+1. **Shared Responsibility Model Has No Legal Weight**: Just descriptive strings
+2. **GDPR/CCPA Claims Are Unsubstantiated Booleans**: No evidence required
+3. **Accessibility Compliance is Self-Declared**: No VPAT, no audit reports
+4. **Security Certifications Cannot Be Verified**: No certificate numbers, audit periods
+5. **Data Retention Policy is Underspecified**: Only three options
+6. **PII Handling Lacks Classification**: Binary flags for complex topic
+7. **User Rights Implementation Incomplete**: Only 2 of 8 GDPR rights covered
+8. **No Audit Trail Requirements**: Zero mentions of logging
+
+### GOVERNANCE CONCERNS
+
+1. **Fenestra Documents Cannot Be Trusted**: No signing, no verification
+2. **Malicious Capability Advertisements**: Platforms can lie about security features
+3. **Version Security Updates Missing**: No CVE tracking, no security mailing list
+4. **Extension Point Constraints Not Enforced**: supportedComponents not validated
+5. **Custom Component Approval Process Undefined**: Who approves? SLA?
+6. **Security Review Scope is Inadequate**: Private apps may get no review
+7. **No Incident Response Plan**: Zero guidance when incidents occur
+8. **No Change Management**: Documents can change silently
+9. **No Third-Party Risk Management**: Subprocessors, dependencies
+10. **No Legal Framework**: Liability, indemnification unclear
+
+### AGENT INTERACTION RISKS
+
+1. **Prompt Injection via Template Schemas**: Malicious descriptions
+2. **Template Output Hijacking**: UI returns data agent shouldn't trust
+3. **Interaction Chaining Attacks**: Data exfiltration via chained templates
+4. **Event Callback Spoofing**: Fake events to agent
+5. **Context Poisoning**: Inject commands into conversation history
+6. **Protocol Downgrade Attacks**: Force insecure protocol
+7. **UI Invocation Privilege Escalation**: Hidden UI for approvals
+
+### RECOMMENDATIONS FOR SPEC
+
+The spec should add a **Security Considerations** section addressing:
+
+1. **Document Trust**: Recommend signing, describe trust model
+2. **Tooling Validation**: What validators SHOULD check
+3. **Agent Security**: Authentication, rate limiting, permission scoping recommendations
+4. **Compliance Evidence**: How to provide verifiable compliance claims
+5. **URL Validation**: What URLs are safe to fetch
+6. **CSP Best Practices**: Minimum viable CSP policies
+7. **Incident Response**: Recommend security contact, disclosure policy
+
+---
+
+## 5. Synthesis & Recommendations
+
+### Priority Matrix
+
+| Priority | Category | Issue | Effort |
+|----------|----------|-------|--------|
+| P0 | Schema | `extensionTypeConfig` needs discriminated union | Medium |
+| P0 | Schema | Extract prose objects to `$defs` with `$ref` | High |
+| P0 | Schema | Add `patternProperties` for `x-` extensions | Low |
+| P0 | Docs | Fix broken anchor links | Low |
+| P0 | Schema | Align JSON Schema draft version | Low |
+| P1 | Coverage | Add multi-context architecture support | High |
+| P1 | Coverage | Add backend/infrastructure requirements | High |
+| P1 | Coverage | Support multiple extension types per extension point | Medium |
+| P1 | DX | Fix props schema (function type invalid) | Medium |
+| P1 | DX | Add import path construction rules | Medium |
+| P1 | Security | Add Security Considerations section | Medium |
+| P1 | Security | Add agent authentication recommendations | Medium |
+| P2 | Coverage | Add state management model | Medium |
+| P2 | Coverage | Expand authentication flows | Medium |
+| P2 | Coverage | Add deployment/hosting model | Medium |
+| P2 | DX | Add type definition linking | Medium |
+| P2 | DX | Add context data schemas | Medium |
+| P2 | Security | Add granular permission model | Medium |
+| P2 | Compliance | Expand user rights coverage | Low |
+| P3 | DX | Add component dependency graph | Low |
+| P3 | DX | Add performance characteristics | Low |
+| P3 | Coverage | Add rate limits/quotas | Low |
+
+### Key Insight: Scope of Specification
+
+The security review highlighted an important distinction:
+
+**What Fenestra IS:**
+- A description format for platform UI ecosystems
+- A vocabulary for documenting capabilities
+- A schema for tooling to parse and understand platforms
+
+**What Fenestra IS NOT:**
+- An enforcement mechanism
+- A security protocol
+- A compliance certification
+
+Many "security vulnerabilities" are really platform implementation concerns. The spec can't make platforms secure, but it CAN:
+1. Provide vocabulary to describe security posture
+2. Document best practices for spec authors
+3. Recommend validation for tooling
+4. Include Security Considerations section
+
+### Recommended Next Steps
+
+1. **Fix P0 issues** before OAI submission (schema consistency, anchors)
+2. **Add Security Considerations section** documenting trust model and best practices
+3. **Consider phased approach** for coverage gaps (core spec v0.1, extensions v0.2)
+4. **Engage platform partners** to validate real-world fit (HubSpot, Shopify, Slack)
+5. **Build reference tooling** that demonstrates validation patterns
+
+---
+
+*End of Adversarial Reviews*
diff --git a/specs/fenestra/CONTRIBUTING.md b/specs/fenestra/CONTRIBUTING.md
new file mode 100644
index 0000000..02084ec
--- /dev/null
+++ b/specs/fenestra/CONTRIBUTING.md
@@ -0,0 +1,95 @@
+# Contributing to the Fenestra Specification
+
+Thank you for your interest in contributing to the Fenestra Specification! This document provides guidelines for contributing to the specification.
+
+## Ways to Contribute
+
+### Report Issues
+
+If you find an error in the specification or have a suggestion for improvement:
+
+1. Check if an issue already exists in the [issue tracker](https://github.com/friggframework/fenestra-spec/issues)
+2. If not, create a new issue with a clear description
+3. Include examples when possible
+
+### Propose Changes
+
+For changes to the specification:
+
+1. **Minor clarifications**: Open an issue describing the clarification needed
+2. **New features**: Open a discussion or issue to gather feedback before implementation
+3. **Bug fixes**: Open a pull request with a clear description of the fix
+
+### Submit Pull Requests
+
+1. Fork the repository
+2. Create a feature branch from `main`
+3. Make your changes following the style guidelines below
+4. Submit a pull request
+
+## Style Guidelines
+
+### Specification Document
+
+The specification document (`versions/0.1.0.md`) follows these conventions:
+
+- Use RFC 2119 key words (MUST, SHOULD, MAY) in capitals for normative statements
+- Document each object with:
+ - A description paragraph
+ - A "Fixed Fields" table
+ - Examples in YAML format
+- Use consistent table formatting
+- Include anchor links for all object and field names
+
+### Schema Files
+
+JSON Schema files (`schemas/`) should:
+
+- Use JSON Schema Draft 2020-12
+- Include descriptions for all properties
+- Define enums where applicable
+- Support specification extensions via `patternProperties`
+
+### Examples
+
+Example files (`examples/`) should:
+
+- Be valid according to the JSON Schema
+- Demonstrate real-world use cases
+- Include comments explaining key decisions
+
+## Development Setup
+
+```bash
+# Clone the repository
+git clone https://github.com/friggframework/fenestra-spec.git
+cd fenestra-spec
+
+# Install dependencies (for validation tooling)
+npm install
+
+# Validate examples against schema
+npm run validate
+```
+
+## Review Process
+
+1. All changes require review by at least one maintainer
+2. Specification changes require consensus from the working group
+3. CI checks must pass before merging
+
+## Code of Conduct
+
+This project follows the [Contributor Covenant Code of Conduct](https://www.contributor-covenant.org/version/2/1/code_of_conduct/). Please be respectful and constructive in all interactions.
+
+## License
+
+By contributing, you agree that your contributions will be licensed under the Apache License 2.0.
+
+## Questions?
+
+- Open a [GitHub Discussion](https://github.com/friggframework/fenestra-spec/discussions)
+- Join the Fenestra Working Group meetings (schedule TBD)
+- Contact the maintainers
+
+Thank you for helping improve the Fenestra Specification!
diff --git a/specs/fenestra/DIAGRAMS.md b/specs/fenestra/DIAGRAMS.md
new file mode 100644
index 0000000..1593cdf
--- /dev/null
+++ b/specs/fenestra/DIAGRAMS.md
@@ -0,0 +1,506 @@
+# Fenestra Extension Types - Diagrams
+
+This document illustrates the 5 broad extension types and how rendering flows from developer-provided assets to user-visible UI.
+
+---
+
+## Type 1: JSON Response
+
+**Pattern**: Developer provides JSON conforming to platform schema → Platform renders pre-built components
+
+**Examples**: Google Workspace Add-ons, Asana App Components, Slack Block Kit, Pipedrive, Gorgias
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ PLATFORM SIDE │
+│ │
+│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────────────────────┐│
+│ │ User │ │ Platform │ │ Component Renderer ││
+│ │ Triggers │───▶│ Calls │ │ (Platform-owned) ││
+│ │ Action │ │ Endpoint │ │ ││
+│ └─────────────┘ └──────┬───────┘ │ ┌─────┐ ┌─────┐ ┌─────┐ ││
+│ │ │ │Card │ │Form │ │List │ ... ││
+│ │ │ └─────┘ └─────┘ └─────┘ ││
+│ ▼ └────────────────┬────────────────┘│
+│ ┌──────────────┐ │ │
+│ │ Validate │ │ │
+│ │ JSON │ │ │
+│ │ Schema │ │ │
+│ └──────┬───────┘ │ │
+│ │ │ │
+│ ▼ ▼ │
+│ ┌──────────────────────────────────────┐ │
+│ │ Rendered UI in Platform │ │
+│ └──────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────────────────────────────┘
+ ▲
+ │ HTTP Response
+ │ (JSON Payload)
+┌────────────────────────────┴────────────────────────────────────────────────┐
+│ DEVELOPER SIDE │
+│ │
+│ ┌─────────────────────────────────────────────────────────────────────┐ │
+│ │ Developer's Server │ │
+│ │ │ │
+│ │ 1. Receive request with context │ │
+│ │ 2. Fetch/compute data │ │
+│ │ 3. Return JSON matching platform schema │ │
+│ │ │ │
+│ │ Example Response: │ │
+│ │ { │ │
+│ │ "type": "card", │ │
+│ │ "title": "Customer Info", │ │
+│ │ "sections": [ │ │
+│ │ { "type": "keyValue", "key": "Name", "value": "John" } │ │
+│ │ ] │ │
+│ │ } │ │
+│ └─────────────────────────────────────────────────────────────────────┘ │
+│ │
+│ Developer provides: Endpoint URL, JSON responses │
+│ Developer does NOT provide: Any rendering code, components, or UI logic │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Key Characteristics**:
+- No JS SDK typically needed
+- Platform owns ALL rendering
+- Developer only controls data and which component types to use
+- Limited customization (can't create new component types)
+- Fast to build, but constrained
+
+---
+
+## Type 2: Coded Components
+
+**Pattern**: Developer writes React code using platform's UI Kit → Code runs in platform's runtime
+
+**Examples**: Salesforce LWC, HubSpot UI Extensions, Zendesk Apps, Canva Apps SDK
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ PLATFORM SIDE │
+│ │
+│ ┌─────────────┐ ┌──────────────────────────────────────────────────┐ │
+│ │ User │ │ Platform Runtime │ │
+│ │ Opens │───▶│ │ │
+│ │ Extension │ │ ┌────────────────────────────────────────────┐ │ │
+│ └─────────────┘ │ │ Sandboxed Execution Environment │ │ │
+│ │ │ │ │ │
+│ │ │ ┌──────────────────────────────────────┐ │ │ │
+│ │ │ │ Developer's React Code │ │ │ │
+│ │ │ │ │ │ │ │
+│ │ │ │ import { Button, Card } from SDK │ │ │ │
+│ │ │ │ │ │ │ │
+│ │ │ │ │ │ │ │
+│ │ │ │ │ │ │ │
+│ │ │ │ │ │ │ │
+│ │ │ └──────────────────────────────────────┘ │ │ │
+│ │ │ │ │ │ │
+│ │ │ ▼ │ │ │
+│ │ │ ┌──────────────────────────────────────┐ │ │ │
+│ │ │ │ Platform UI Kit Components │ │ │ │
+│ │ │ │ (Button, Card, Input, Modal...) │ │ │ │
+│ │ │ └──────────────────────────────────────┘ │ │ │
+│ │ └────────────────────────────────────────────┘ │ │
+│ │ │ │
+│ │ ┌────────────────────────────────────────────┐ │ │
+│ │ │ Optional: JS SDK for host interaction │ │ │
+│ │ │ hubspot.crm.actions.openModal() │ │ │
+│ │ │ hubspot.ui.showToast() │ │ │
+│ │ └────────────────────────────────────────────┘ │ │
+│ └──────────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────────────────────────────┘
+ ▲
+ │ Bundle (JS/CSS)
+ │
+┌────────────────────────────┴────────────────────────────────────────────────┐
+│ DEVELOPER SIDE │
+│ │
+│ ┌─────────────────────────────────────────────────────────────────────┐ │
+│ │ Developer's Codebase │ │
+│ │ │ │
+│ │ package.json: │ │
+│ │ "@hubspot/ui-extensions": "^0.11.0" │ │
+│ │ │ │
+│ │ MyExtension.tsx: │ │
+│ │ import { Button, Card, Text } from '@hubspot/ui-extensions'; │ │
+│ │ import { hubspot } from '@hubspot/ui-extensions'; │ │
+│ │ │ │
+│ │ export function MyExtension({ context }) { │ │
+│ │ return ( │ │
+│ │ │ │
+│ │ Hello {context.user.name} │ │
+│ │ │ │
+│ │ │ │
+│ │ ); │ │
+│ │ } │ │
+│ └─────────────────────────────────────────────────────────────────────┘ │
+│ │
+│ Developer provides: React code, component composition, business logic │
+│ Developer uses: Platform's component library (required or recommended) │
+│ Developer may NOT: Use arbitrary HTML/CSS (platform-dependent) │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Key Characteristics**:
+- Developer writes actual code (usually React/TypeScript)
+- Platform provides component library (may be required or optional)
+- Code runs in platform's sandboxed environment
+- Often paired with JS SDK for host interactions
+- More flexibility than JSON, but still constrained to SDK
+
+**Variants**:
+| Variant | BYO Components? | Example |
+|---------|-----------------|---------|
+| **Strict** | No - SDK only | HubSpot UI Extensions |
+| **Recommended** | Yes, but SDK preferred | Canva Apps |
+| **Flexible** | Yes - any React | Some Zendesk apps |
+
+---
+
+## Type 3: Iframe
+
+**Pattern**: Developer provides full web app at a URL → Platform embeds in iframe
+
+**Examples**: Front Plugins, Intercom Apps, legacy integrations
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ PLATFORM SIDE │
+│ │
+│ ┌─────────────┐ ┌──────────────────────────────────────────────────┐ │
+│ │ User │ │ Platform UI │ │
+│ │ Opens │───▶│ │ │
+│ │ Extension │ │ ┌────────────────────────────────────────────┐ │ │
+│ └─────────────┘ │ │ │ │ │
+│ │ │ │ │ │
+│ │ │ │ │ │
+│ │ └────────────────────────────────────────────┘ │ │
+│ │ ▲ │ │
+│ │ │ postMessage │ │
+│ │ ▼ │ │
+│ │ ┌────────────────────────────────────────────┐ │ │
+│ │ │ Optional: JS SDK (loaded in iframe) │ │ │
+│ │ │ window.parent.postMessage(...) │ │ │
+│ │ │ or SDK wrapper: Front.send('...') │ │ │
+│ │ └────────────────────────────────────────────┘ │ │
+│ └──────────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────────────────────────────┘
+ ▲
+ │ HTTP (HTML/JS/CSS)
+ │
+┌────────────────────────────┴────────────────────────────────────────────────┐
+│ DEVELOPER SIDE │
+│ │
+│ ┌─────────────────────────────────────────────────────────────────────┐ │
+│ │ Developer's Hosted Web Application │ │
+│ │ │ │
+│ │ - Any framework: React, Vue, Svelte, vanilla JS, etc. │ │
+│ │ - Any styling: Tailwind, Bootstrap, custom CSS │ │
+│ │ - Full control over rendering │ │
+│ │ │ │
+│ │ Optional: Load platform's JS SDK for host interaction │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ └─────────────────────────────────────────────────────────────────────┘ │
+│ │
+│ Developer provides: Full web app (HTML, CSS, JS), hosting │
+│ Developer controls: Everything about rendering and behavior │
+│ Platform provides: Iframe container, optional SDK for communication │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Key Characteristics**:
+- Maximum flexibility for developer
+- Platform has minimal control over UI
+- Often uses postMessage for communication
+- May or may not have a JS SDK
+- Developer responsible for styling consistency
+- Security via iframe sandbox attributes
+
+---
+
+## Type 4: Embedded SDK
+
+**Pattern**: Developer embeds platform's SDK into their own application
+
+**Examples**: Stripe Elements, Typeform Embed, Calendly, Analytics SDKs
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ DEVELOPER'S APPLICATION │
+│ (The developer IS the platform here) │
+│ │
+│ ┌─────────────────────────────────────────────────────────────────────┐ │
+│ │ Developer's Web App │ │
+│ │ │ │
+│ │ │ │
+│ │
│ │
+│ │ My Checkout Page
│ │
+│ │ │ │
+│ │ │ │
+│ │ ┌────────────────────────────────────────────────────────┐ │ │
+│ │ │ │ │ │
+│ │ │ ┌──────────────────────────────────────────────────┐ │ │ │
+│ │ │ │ ┌──────────────────┐ ┌──────────────────┐ │ │ │ │
+│ │ │ │ │ Card Number │ │ Expiry │ │ │ │ │
+│ │ │ │ │ 4242 4242 4242 │ │ 12/25 │ │ │ │ │
+│ │ │ │ └──────────────────┘ └──────────────────┘ │ │ │ │
+│ │ │ │ ┌──────────────────┐ │ │ │ │
+│ │ │ │ │ CVC │ [Pay $99.00] │ │ │ │
+│ │ │ │ │ 123 │ │ │ │ │
+│ │ │ │ └──────────────────┘ │ │ │ │
+│ │ │ └──────────────────────────────────────────────────┘ │ │ │
+│ │ │
│ │ │
+│ │ │ (Stripe Elements - platform-rendered, secure) │ │ │
+│ │ └────────────────────────────────────────────────────────┘ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ └─────────────────────────────────────────────────────────────────────┘ │
+│ │
+│ Developer provides: Host application, mount point, configuration │
+│ Platform provides: SDK that renders secure/compliant UI components │
+└─────────────────────────────────────────────────────────────────────────────┘
+ │
+ │ SDK loaded from
+ ▼
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ PLATFORM SIDE │
+│ │
+│ ┌─────────────────────────────────────────────────────────────────────┐ │
+│ │ Platform's Embeddable SDK (e.g., Stripe.js) │ │
+│ │ │ │
+│ │ - Renders UI components in developer's page │ │
+│ │ - Handles sensitive data (PCI compliance for payments) │ │
+│ │ - Provides JS API for developer interaction │ │
+│ │ - May use iframes internally for security isolation │ │
+│ │ │ │
+│ │ Developer calls: │ │
+│ │ stripe.confirmPayment() │ │
+│ │ stripe.elements.create('card', options) │ │
+│ │ element.on('change', callback) │ │
+│ └─────────────────────────────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Key Characteristics**:
+- **Inverted relationship**: Developer's app is the host, platform provides embedded component
+- Platform maintains control over sensitive rendering (e.g., payment fields)
+- Developer integrates via JS SDK with mount points
+- Often for compliance/security (PCI, authentication)
+- Examples: Stripe Elements, PayPal Buttons, Plaid Link, Auth0 Lock
+
+**Note**: This is the "reverse" of the other types - here the developer is building the platform/app, and embedding someone else's UI component.
+
+---
+
+## Cross-Cutting: JavaScript SDK Interaction
+
+Many extension types include a JS SDK for interacting with the host platform:
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ JS SDK INTERACTION PATTERN │
+│ │
+│ ┌─────────────────────────────────────────────────────────────────────┐ │
+│ │ Platform Host Window │ │
+│ │ │ │
+│ │ window.platformSDK = { │ │
+│ │ │ │
+│ │ // Context │ │
+│ │ context: { │ │
+│ │ user: { id, name, email }, │ │
+│ │ record: { id, type, properties }, │ │
+│ │ locale: 'en-US' │ │
+│ │ }, │ │
+│ │ │ │
+│ │ // UI Actions │ │
+│ │ ui: { │ │
+│ │ showToast(message, type), │ │
+│ │ openModal(config), │ │
+│ │ closePanel() │ │
+│ │ }, │ │
+│ │ │ │
+│ │ // Data Actions │ │
+│ │ data: { │ │
+│ │ createRecord(type, data), │ │
+│ │ updateRecord(id, data), │ │
+│ │ query(type, filters) │ │
+│ │ }, │ │
+│ │ │ │
+│ │ // Events │ │
+│ │ on(event, callback), │ │
+│ │ off(event, callback) │ │
+│ │ }; │ │
+│ │ │ │
+│ └─────────────────────────────────────────────────────────────────────┘ │
+│ │
+│ Examples: │
+│ - Miro: window.miro.board.createShape(...) │
+│ - Front: Front.on('conversation', callback) │
+│ - Figma: figma.currentPage.selection │
+│ - Canva: canva.design.addNativeElement(...) │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**JS SDK should document**:
+- Global object name (`window.miro`, `window.Front`, etc.)
+- Available namespaces (ui, data, context, etc.)
+- Method signatures and return types
+- Event types and payloads
+- Async patterns (Promises, callbacks)
+
+---
+
+## Type 5: Agent UI
+
+**Pattern**: AI agent drives UI through pre-declared templates + custom iframe fallback
+
+**Examples**: MCP Apps hosts, AI assistant sidebars, LLM-powered interfaces
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ PLATFORM/HOST SIDE │
+│ │
+│ ┌─────────────┐ ┌──────────────────────────────────────────────────┐ │
+│ │ AI Agent │ │ Host Application │ │
+│ │ (Server) │───▶│ │ │
+│ │ │ │ ┌────────────────────────────────────────────┐ │ │
+│ └─────────────┘ │ │ Template Renderer │ │ │
+│ │ │ │ │ │ │
+│ │ │ │ Agent invokes template: │ │ │
+│ │ │ │ ┌────────────────────────────────────┐ │ │ │
+│ │ │ │ │ { │ │ │ │
+│ │ │ │ │ "template": "form", │ │ │ │
+│ │ │ │ │ "data": { │ │ │ │
+│ │ JSON-RPC │ │ │ "title": "Enter Details", │ │ │ │
+│ │ over MCP │ │ │ "schema": { ... } │ │ │ │
+│ ▼ │ │ │ } │ │ │ │
+│ ┌───────────┐ │ │ │ } │ │ │ │
+│ │ Template │ │ │ └────────────────────────────────────┘ │ │ │
+│ │ Request │──────│ │ │ │ │ │
+│ └───────────┘ │ │ ▼ │ │ │
+│ │ │ ┌────────────────────────────────────┐ │ │ │
+│ │ │ │ Pre-built Templates │ │ │ │
+│ │ │ │ ┌──────┐ ┌──────┐ ┌──────┐ │ │ │ │
+│ │ │ │ │ Form │ │Confirm││Result│ ... │ │ │ │
+│ │ │ │ └──────┘ └──────┘ └──────┘ │ │ │ │
+│ │ │ │ (JSON Forms, platform components) │ │ │ │
+│ │ │ └────────────────────────────────────┘ │ │ │
+│ │ │ │ │ │
+│ │ └────────────────────────────────────────────┘ │ │
+│ │ │ │
+│ │ ┌────────────────────────────────────────────┐ │ │
+│ │ │ OR: Custom Iframe Fallback │ │ │
+│ │ │ │ │ │
+│ │ │ Agent opens custom UI when templates │ │ │
+│ │ │ aren't sufficient: │ │ │
+│ │ │ ┌──────────────────────────────────────┐ │ │ │
+│ │ │ │ │ │ │ │
+│ │ │ └──────────────────────────────────────┘ │ │ │
+│ │ └────────────────────────────────────────────┘ │ │
+│ │ ▲ │ │
+│ │ │ User interaction │ │
+│ │ ▼ │ │
+│ │ ┌────────────────────────────────────────────┐ │ │
+│ │ │ Event Flow Back to Agent │ │ │
+│ │ │ - Form submitted → agent receives data │ │ │
+│ │ │ - Confirmation → agent continues/stops │ │ │
+│ │ │ - Custom action → agent handles event │ │ │
+│ │ └────────────────────────────────────────────┘ │ │
+│ └──────────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────────────────────────────┘
+ ▲
+ │ MCP Protocol
+ │
+┌────────────────────────────┴────────────────────────────────────────────────┐
+│ AGENT/MCP SERVER SIDE │
+│ │
+│ ┌─────────────────────────────────────────────────────────────────────┐ │
+│ │ MCP Server with UI Capability │ │
+│ │ │ │
+│ │ Declares UI templates in manifest: │ │
+│ │ { │ │
+│ │ "templates": ["form", "confirmation", "progress", "result"], │ │
+│ │ "customUIAllowed": true │ │
+│ │ } │ │
+│ │ │ │
+│ │ During tool execution: │ │
+│ │ 1. Agent decides UI is needed │ │
+│ │ 2. Invokes template: showUI("form", { schema, data }) │ │
+│ │ 3. Waits for user response │ │
+│ │ 4. Continues processing with user input │ │
+│ │ │ │
+│ │ Or for complex UI: │ │
+│ │ 1. Opens custom iframe: openCustomUI("https://...") │ │
+│ │ 2. Communicates via JSON-RPC in iframe │ │
+│ │ 3. Receives events and responds │ │
+│ └─────────────────────────────────────────────────────────────────────┘ │
+│ │
+│ Agent provides: Template invocations, custom iframe URL (optional) │
+│ Agent does NOT provide: Template rendering logic (host handles that) │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Key Characteristics**:
+- AI agent drives the UI programmatically
+- Pre-declared templates for common patterns (forms, confirmations, progress)
+- Custom iframe escape hatch for complex interactions
+- JSON-RPC communication over MCP protocol
+- JSON Forms used for structured input collection
+- Agent can chain multiple UI interactions
+
+**Comparison to Other Types**:
+| Aspect | Agent UI | JSON Response | Iframe |
+|--------|----------|---------------|--------|
+| Who decides what UI? | AI Agent | Developer endpoint | Developer app |
+| Pre-declared templates? | Yes | Yes | No |
+| Custom UI? | Via iframe fallback | No | Primary mode |
+| Interaction pattern | Agent-driven loop | Request-response | User-driven |
+
+---
+
+## Summary Table
+
+| Type | Who Renders? | Developer Provides | BYO Styling? | JS SDK? |
+|------|--------------|-------------------|--------------|---------|
+| **JSON Response** | Platform | JSON payloads | No | Rarely |
+| **Coded Components** | Platform (from dev code) | React code + SDK components | Limited | Often |
+| **Iframe** | Developer | Full web app | Yes | Optional |
+| **Embedded SDK** | Platform (in dev's app) | Mount point + config | Limited | Required |
+| **Agent UI** | Platform (from agent invocations) | Template data + optional iframe | Via iframe only | Required (MCP) |
diff --git a/specs/fenestra/ECOSYSTEM-MAPPING.md b/specs/fenestra/ECOSYSTEM-MAPPING.md
new file mode 100644
index 0000000..a622669
--- /dev/null
+++ b/specs/fenestra/ECOSYSTEM-MAPPING.md
@@ -0,0 +1,732 @@
+# Fenestra Ecosystem Mapping
+
+This document maps real-world platforms to the 5 extension types defined in the Fenestra specification.
+
+---
+
+## Type 1: JSON Response
+
+Platform renders pre-built components from JSON payloads returned by developer's endpoint.
+
+| Platform | JSON Format | Components | Timeout | JS SDK | Docs |
+|----------|-------------|------------|---------|--------|------|
+| **Google Workspace** | `google.apps.card.v1` | 15+ widgets | Not specified | No (server-side) | [Link](https://developers.google.com/workspace/add-ons/concepts/card-interfaces) |
+| **Asana** | OpenAPI-based | Modal Forms, Lookups, Widgets | 10s | No | [Link](https://developers.asana.com/docs/app-components) |
+| **Gorgias** | Custom JSON | 5+ element types | ~10s | No | [Link](https://developers.gorgias.com/docs/create-integrations-and-widgets-programmatically) |
+| **Pipedrive** | JSON Schema | Panels, Modals | 10s | Optional (for custom UI) | [Link](https://pipedrive.readme.io/docs/app-extensions-json-panels) |
+| **Slack Block Kit** | Custom JSON | 8 blocks, 10+ elements | Not specified | No | [Link](https://docs.slack.dev/block-kit/) |
+| **MS Adaptive Cards** | Platform-agnostic JSON | 25+ elements | Varies | Yes (rendering) | [Link](https://adaptivecards.io/) |
+
+### Detailed Breakdown
+
+#### Google Workspace Add-ons
+```yaml
+platform: Google Workspace
+type: jsonResponse
+schema:
+ format: google.apps.card.v1
+ version: draft-07
+ encoding: UTF-8
+endpoint:
+ method: POST
+ contextProvided:
+ - commonEventObject
+ - authorizationEventObject
+ - hostAppContext (gmail/drive/calendar)
+components:
+ - TextParagraph
+ - TextInput
+ - Button / ButtonList
+ - SelectionInput (max 100 items)
+ - DateTimePicker
+ - DecoratedText
+ - Divider
+ - Grid
+ - Image / Icon
+limits:
+ maxWidgets: 100
+```
+
+#### Slack Block Kit
+```yaml
+platform: Slack
+type: jsonResponse
+schema:
+ format: custom
+ structure: Array of blocks with type field
+endpoint:
+ method: POST
+ encoding: application/x-www-form-urlencoded
+ payloadTypes:
+ - block_actions
+ - view_submission
+ - view_closed
+ - shortcut
+components:
+ blocks:
+ - section
+ - header
+ - actions
+ - input
+ - context
+ - divider
+ - rich_text
+ - image
+ - file
+ elements:
+ - button
+ - select / multi_select
+ - text_input
+ - datepicker / timepicker
+ - checkboxes / radio_buttons
+ - overflow
+limits:
+ blocksPerMessage: 50
+ blocksPerModal: 100
+```
+
+#### Microsoft Adaptive Cards
+```yaml
+platform: Microsoft Teams / Outlook / Windows
+type: jsonResponse
+schema:
+ format: AdaptiveCard
+ version: "1.5" # Teams, 1.2 for mobile
+ platformAgnostic: true
+components:
+ elements:
+ - TextBlock
+ - RichTextBlock
+ - Image
+ - Media
+ - Container
+ - ColumnSet / Column
+ - FactSet
+ - Table (v1.5+)
+ inputs:
+ - Input.Text
+ - Input.Number
+ - Input.Date
+ - Input.Time
+ - Input.Toggle
+ - Input.ChoiceSet
+ actions:
+ - Action.OpenUrl
+ - Action.Submit
+ - Action.ShowCard
+ - Action.ToggleVisibility
+ - Action.Execute
+jsSdk:
+ package: "@microsoft/adaptivecards"
+ purpose: Client-side rendering
+```
+
+---
+
+## Type 2: Coded Components
+
+Developer writes code (typically React) using platform's UI Kit. Code runs in platform's runtime.
+
+| Platform | SDK Package | Framework | BYO Allowed? | Host API | Docs |
+|----------|-------------|-----------|--------------|----------|------|
+| **HubSpot** | `@hubspot/ui-extensions` | React | No | SDK imports | [Link](https://developers.hubspot.com/docs/platform/ui-extensions-sdk) |
+| **Salesforce LWC** | `lwc`, `lightning-base-components` | LWC (Web Components) | Restricted | `lightning/*` imports | [Link](https://developer.salesforce.com/docs/platform/lwc/overview) |
+| **Canva** | `@canva/app-ui-kit` | React 19 | Yes (constrained) | `@canva/platform` | [Link](https://www.canva.dev/docs/apps/app-ui-kit/) |
+| **Shopify** | CDN (Web Components) | Web Components | Discouraged | `shopify` global | [Link](https://shopify.dev/docs/api/app-bridge) |
+| **Monday.com** | `@vibe/core`, `monday-sdk-js` | Agnostic (React rec.) | Yes | `mondaySDK` | [Link](https://developer.monday.com/apps/docs/vibe-design-system) |
+
+### Detailed Breakdown
+
+#### HubSpot UI Extensions
+```yaml
+platform: HubSpot
+type: codedComponents
+sdk:
+ package: "@hubspot/ui-extensions"
+ framework: React
+ runtime: Sandboxed iframe
+componentRequirement:
+ level: required
+ byoAllowed: false
+ rationale: "Sandboxed iframe prevents DOM access"
+components:
+ standard:
+ - Button, ButtonRow
+ - Text, Heading
+ - Input, TextArea, Select
+ - Card, Tile, Flex, Box
+ - Modal, Panel
+ - Table, DescriptionList
+ - Alert, Badge, Tag
+ - LoadingSpinner, ProgressBar
+ crmData:
+ package: "@hubspot/ui-extensions/crm"
+ components:
+ - CrmAssociationTable
+ - CrmPropertyList
+ - CrmActionButton
+hostApi:
+ methods:
+ - runServerlessFunction()
+ - actions from SDK
+```
+
+#### Salesforce Lightning Web Components
+```yaml
+platform: Salesforce
+type: codedComponents
+sdk:
+ package: lwc
+ componentLibrary: lightning-base-components
+ framework: LWC (Web Components based)
+componentRequirement:
+ level: required
+ byoAllowed: restricted
+ constraints:
+ - No third-party web components with npm dependencies
+ - Can load JS libraries via Static Resources
+ - Must use lwc:dom="manual" for external DOM manipulation
+components:
+ categories:
+ - Input components
+ - Navigation components
+ - Table and tree components
+ - Visual components
+ - Form components
+ - Button variants (base, neutral, brand, destructive, success)
+hostApi:
+ pattern: ES6 module imports
+ namespaces:
+ - lightning/platformResourceLoader
+ - lightning/uiRecordApi
+ - lightning/navigation
+```
+
+#### Canva Apps SDK
+```yaml
+platform: Canva
+type: codedComponents
+sdk:
+ package: "@canva/app-ui-kit"
+ platformSdk: "@canva/platform"
+ framework: React 19
+componentRequirement:
+ level: recommended
+ byoAllowed: true
+ constraints:
+ - Must wrap in AppUiProvider
+ - Should use design tokens for consistency
+ - Public apps: strongly recommended for design guidelines
+ - Team apps: optional but better UX
+components:
+ - Button, LinkButton
+ - Rows, Text, Title
+ - Select (with multi-select)
+ - AudioCard, ImageCard
+designTokens:
+ formats:
+ - JavaScript variables
+ - CSS variables
+ - React props
+```
+
+---
+
+## Type 3: Iframe
+
+Developer provides full web app at URL. Platform loads in iframe with optional SDK for communication.
+
+| Platform | SDK Package | Global Object | Communication | Docs |
+|----------|-------------|---------------|---------------|------|
+| **Front** | `@frontapp/plugin-sdk` | `Front` | Observable pattern | [Link](https://dev.frontapp.com/docs/plugin-overview) |
+| **Zendesk** | `zendesk_app_framework_sdk` | `ZAFClient` | get/set/invoke | [Link](https://developer.zendesk.com/api-reference/apps/apps-core-api/client_api/) |
+| **Freshdesk** | `fresh_client.js` | `app` → `client` | Promise-based | [Link](https://developers.freshworks.com/docs/app-sdk/v2.3/freshdesk/) |
+| **Intercom** | `@intercom/messenger-js-sdk` | `Intercom` | HTTP POST + Sheets | [Link](https://developers.intercom.com/docs/canvas-kit) |
+| **Salesforce Canvas** | Canvas SDK | `Sfdc.canvas` | Signed requests | [Link](https://developer.salesforce.com/docs/atlas.en-us.platform_connect.meta/platform_connect/canvas_framework_using_sdk.htm) |
+| **Figma** | `@figma/plugin-typings` | `figma` | postMessage | [Link](https://developers.figma.com/docs/plugins/) |
+
+### Detailed Breakdown
+
+#### Front Plugins
+```yaml
+platform: Front
+type: iframe
+extensionPoints:
+ - sidebar
+ - composer
+sdk:
+ package: "@frontapp/plugin-sdk"
+ cdn: "https://dl.frontapp.com/libs/frontjs.min.js"
+ globalObject: Front
+communication:
+ pattern: Observable
+ contextTypes:
+ - noConversation
+ - singleConversation
+ - multiConversations
+ methods:
+ - Front.contextUpdates (Observable)
+ - context.listMessages()
+ - context.createDraft()
+ - context.fetchConversation()
+styling:
+ control: full
+ platformRestrictions: none
+```
+
+#### Zendesk Apps
+```yaml
+platform: Zendesk
+type: iframe
+sdk:
+ package: zendesk_app_framework_sdk
+ cdn: "https://static.zdassets.com/zendesk_app_framework_sdk/2.0/zaf_sdk.min.js"
+ globalObject: ZAFClient
+communication:
+ init: ZAFClient.init()
+ methods:
+ - client.get(path) # Read framework data
+ - client.set(path, value) # Write framework data
+ - client.invoke(method) # Run framework methods
+ - client.request(options) # HTTP requests
+ - client.on(event, handler) # Event listeners
+componentRequirement:
+ level: optional
+ componentLibrary: "@zendeskgarden/*"
+ byoAllowed: true
+```
+
+#### Figma Plugins
+```yaml
+platform: Figma
+type: iframe
+architecture:
+ mainThread:
+ - Accesses Figma scene
+ - No browser APIs
+ - Sandboxed
+ uiIframe:
+ - Accesses browser APIs
+ - No Figma scene access
+ - Full framework freedom
+sdk:
+ package: "@figma/plugin-typings"
+ globalObject: figma
+ uiMethods:
+ - figma.showUI(html)
+ - figma.ui.show() / hide() / close()
+ - figma.ui.postMessage()
+communication:
+ pattern: postMessage between main thread and UI
+componentRequirement:
+ level: optional
+ byoAllowed: true
+ notes: "Community component libraries available"
+```
+
+---
+
+## Type 4: Embedded SDK
+
+Platform provides SDK that developer embeds in their own application. Platform renders secure UI components.
+
+| Platform | SDK Package | Global Object | Purpose | Theming | Docs |
+|----------|-------------|---------------|---------|---------|------|
+| **Stripe Elements** | `@stripe/stripe-js` | `Stripe` | Payments | Appearance API | [Link](https://docs.stripe.com/payments/elements) |
+| **Plaid Link** | `react-plaid-link` | `Plaid` | Bank linking | Dashboard config | [Link](https://plaid.com/docs/link/web/) |
+| **PayPal Buttons** | CDN only | `paypal` | Payments | Style options | [Link](https://developer.paypal.com/sdk/js/reference/) |
+| **Auth0 Lock** | `auth0-lock` | `Auth0Lock` | Authentication | Theme options | [Link](https://auth0.com/docs/libraries/lock) |
+| **Calendly** | CDN only | `Calendly` | Scheduling | Color customization | [Link](https://help.calendly.com/hc/en-us/articles/31618265722775) |
+| **Typeform** | `@typeform/embed` | `tf` | Forms | Size/behavior | [Link](https://www.typeform.com/developers/embed/) |
+
+### Detailed Breakdown
+
+#### Stripe Elements
+```yaml
+platform: Stripe
+type: embeddedSdk
+purpose: PCI-compliant payment collection
+sdk:
+ package: "@stripe/stripe-js"
+ reactPackage: "@stripe/react-stripe-js"
+ cdn: "https://js.stripe.com/v3/" # Must load from CDN
+ globalObject: Stripe
+methods:
+ - loadStripe(publishableKey)
+ - stripe.elements(options)
+ - elements.create(type, options)
+ - element.mount(selector)
+ - stripe.confirmPayment(options)
+communication:
+ pattern: callbacks + promises
+ events:
+ - element.on('change', handler)
+ - element.on('ready', handler)
+ - element.on('focus', handler)
+theming:
+ system: Appearance API
+ prebuiltThemes:
+ - default
+ - stripe
+ - night
+ - flat
+ variables:
+ - colorPrimary
+ - colorBackground
+ - fontFamily
+ - borderRadius
+ rules: CSS-like selectors
+```
+
+#### Plaid Link
+```yaml
+platform: Plaid
+type: embeddedSdk
+purpose: Bank account linking
+sdk:
+ package: react-plaid-link
+ cdn: "https://cdn.plaid.com/link/v2/stable/link-initialize.js"
+ globalObject: Plaid
+methods:
+ - Plaid.create(config)
+ - handler.open()
+ - handler.exit()
+ - handler.destroy()
+communication:
+ pattern: callbacks
+ events:
+ - onSuccess(public_token, metadata)
+ - onExit(err, metadata)
+ - onEvent(eventName, metadata)
+ eventTypes:
+ - OPEN
+ - TRANSITION_VIEW
+ - ERROR
+ - EXIT
+ - HANDOFF
+theming:
+ location: Dashboard
+ options:
+ - Color schemes
+ - Text strings
+ - Overlay customization
+```
+
+#### Typeform Embed
+```yaml
+platform: Typeform
+type: embeddedSdk
+purpose: Embeddable forms and surveys
+sdk:
+ package: "@typeform/embed"
+ reactPackage: "@typeform/embed-react"
+ cdn: "https://embed.typeform.com/next/embed.js"
+ globalObject: tf
+embedTypes:
+ - createWidget() # Inline
+ - createPopup() # Modal
+ - createSlider() # Slide-in
+ - createSidetab() # Side button
+methods:
+ - Returns { open, close, toggle, refresh }
+communication:
+ pattern: callbacks
+ events:
+ - onReady({ formId, isClosed })
+ - onStarted({ formId, responseId })
+ - onQuestionChanged({ formId, ref })
+ - onHeightChanged({ formId, ref, height })
+ - onSubmit({ formId, responseId })
+theming:
+ options:
+ - width / height (CSS units)
+ - hideHeaders
+ - autoClose (ms)
+ - autoResize
+ sidetab:
+ - Full color/dimension customization
+```
+
+---
+
+## Cross-Cutting: JavaScript SDK Patterns
+
+Many platforms expose a global object for host interaction:
+
+| Platform | Global Object | Namespaces | Async Pattern |
+|----------|---------------|------------|---------------|
+| Miro | `miro` | `miro.board`, `miro.ui` | Promises |
+| Figma | `figma` | `figma.ui`, `figma.viewport`, `figma.clientStorage` | Sync + postMessage |
+| Front | `Front` | `Front.contextUpdates` | Observable |
+| Zendesk | `ZAFClient` | `client.get/set/invoke` | Promises |
+| Canva | (imported) | `@canva/platform` | Imports |
+| HubSpot | (imported) | `@hubspot/ui-extensions` | Imports |
+| Stripe | `Stripe` | `stripe.elements` | Promises |
+| PayPal | `paypal` | `paypal.Buttons`, `paypal.CardFields` | Callbacks |
+
+### Common SDK Capabilities
+
+```yaml
+jsSdkCapabilities:
+ context:
+ description: "Access current state/environment"
+ examples:
+ - user info (id, name, email)
+ - current record/object
+ - locale/timezone
+ - permissions/scopes
+
+ uiActions:
+ description: "Trigger platform UI elements"
+ examples:
+ - showToast(message)
+ - openModal(config)
+ - resize(dimensions)
+ - closePanel()
+
+ dataActions:
+ description: "CRUD operations on platform data"
+ examples:
+ - createRecord(type, data)
+ - updateRecord(id, data)
+ - query(type, filters)
+ - deleteRecord(id)
+
+ events:
+ description: "Subscribe to platform events"
+ patterns:
+ - sdk.on(event, callback)
+ - sdk.off(event, callback)
+ - Observable streams
+```
+
+---
+
+## Hybrid Platforms
+
+Some platforms support multiple extension types:
+
+| Platform | Types Supported | Notes |
+|----------|-----------------|-------|
+| **Pipedrive** | JSON + Iframe | JSON for simple panels, iframe for custom UI |
+| **HubSpot** | JSON (Timeline) + Coded | Timeline Events = JSON, UI Extensions = React |
+| **Salesforce** | LWC + Canvas (iframe) | LWC for Lightning, Canvas for legacy/external |
+| **Zendesk** | Coded + Iframe | Can use Garden components or full custom UI |
+| **Intercom** | JSON (Canvas Kit) + Iframe (Sheets) | Canvas Kit for Messenger cards, Sheets for complex UI |
+
+---
+
+## Workflow & Automation Platforms
+
+Integration/automation platforms with their own UI extension models.
+
+| Platform | Types Supported | UI Definition | Developer Provides | Docs |
+|----------|-----------------|---------------|-------------------|------|
+| **Zapier** | JSON + Coded | Field defs + Interfaces | Field schemas, triggers | [Link](https://docs.zapier.com/) |
+| **Make.com** | JSON (RPC) | Parameter specs | Module config, RPC endpoints | [Link](https://developers.make.com/) |
+| **Power Automate** | JSON (OpenAPI + Adaptive Cards) | OpenAPI 2.0 + Card JSON | API spec, card definitions | [Link](https://learn.microsoft.com/en-us/connectors/) |
+
+---
+
+## ERP Platforms
+
+Enterprise Resource Planning systems with UI customization capabilities.
+
+| Platform | Types Supported | UI Definition | Developer Provides | Docs |
+|----------|-----------------|---------------|-------------------|------|
+| **NetSuite** | JSON + Coded (SuiteScript + SPAs) | Point-click + SuiteScript API + JSX | Code or config | [Link](https://docs.oracle.com/en/cloud/saas/netsuite/) |
+
+### Detailed Breakdown
+
+#### Zapier Apps
+```yaml
+platform: Zapier
+type: hybrid (jsonResponse + codedComponents)
+approaches:
+ platformUI:
+ type: jsonResponse
+ description: "JSON field definitions for triggers/actions"
+ fieldTypes:
+ - text, email, url, password
+ - dropdown (static/dynamic)
+ - checkbox, radio, toggle
+ - date/datetime, code
+ dynamicFields: true (via hidden triggers)
+
+ interfaces:
+ type: codedComponents
+ description: "No-code component builder for custom pages"
+ components:
+ - Form, Table, Kanban
+ - Button, Layout
+ - Media, Rich Text, Embed
+
+sdk:
+ package: "@zapier/platform-sdk" # Optional, for CLI
+ globalObject: none
+ jsSdk: false # Platform controls rendering
+
+constraints:
+ - Input forms optional for triggers, required for actions
+ - Dynamic fields limited in Platform UI (full support in CLI)
+ - Custom styling not allowed
+ - Interfaces components have predefined styling
+```
+
+#### Make.com (Integromat)
+```yaml
+platform: Make.com
+type: jsonResponse
+description: "RPC-driven parameter system for dynamic fields"
+
+uiDefinition:
+ format: Make parameter specification
+ fieldTypes:
+ - text (all text-based inputs)
+ - select (static or RPC-generated)
+ - search button (large datasets)
+ - checkbox, radio, file
+
+rpcSystem:
+ description: "Remote Procedure Calls for runtime field generation"
+ types:
+ dynamicOptions: "Generates dropdown/search options from API"
+ dynamicFields: "Fetches field definitions from server"
+ output: "Array of { label, value } objects"
+ nesting: true # RPCs can call other RPCs
+
+sdk:
+ package: none # REST/GraphQL to external services
+ globalObject: none
+
+constraints:
+ - No npm packages; must use external API calls
+ - Type conversion needed (Make uses "text" not "string")
+ - Cannot build custom React components or iframe UIs
+ - Field types limited to platform-supported types
+```
+
+#### Power Automate
+```yaml
+platform: Power Automate
+type: hybrid (jsonResponse)
+approaches:
+ customConnectors:
+ type: jsonResponse
+ description: "OpenAPI 2.0 based connector definitions"
+ format: OpenAPI 2.0 (Swagger)
+ inputTypes:
+ - All primitives (string, number, boolean, integer)
+ - Array/object structures
+ - Enums (dropdown options)
+ - File upload/download
+ maxFileSize: 1MB
+ authentication: API Key, OAuth, Basic
+
+ adaptiveCards:
+ type: jsonResponse
+ description: "Platform-agnostic card format"
+ format: AdaptiveCard JSON
+ version: "1.5" # Teams, 1.2 for mobile
+ components:
+ - TextBlock, RichTextBlock
+ - Input.Text, Input.Number, Input.Date, Input.Time
+ - Input.Toggle, Input.ChoiceSet
+ - Container, ColumnSet, Table
+ - Button actions (OpenUrl, Submit, ShowCard)
+
+copilotStudio:
+ type: agentUI
+ description: "Ask with Adaptive Card nodes for AI interactions"
+
+sdk:
+ adaptiveCards: "@microsoft/adaptivecards"
+ purpose: Client-side card rendering
+
+constraints:
+ - Connectors limited to OpenAPI 2.0 format
+ - No custom code execution in connectors
+ - Adaptive Cards: restricted component set, no arbitrary HTML/CSS
+ - Security/compliance validation required for published connectors
+```
+
+#### NetSuite
+```yaml
+platform: NetSuite
+type: hybrid (jsonResponse + codedComponents)
+approaches:
+ customization:
+ type: jsonResponse
+ description: "Point-and-click form customization"
+ capabilities:
+ - Field visibility/organization
+ - Drag-and-drop UI
+ codeRequired: false
+
+ suiteScript:
+ type: codedComponents
+ description: "Server-side UI component rendering"
+ framework: SuiteScript 2.x
+ module: N/ui/serverWidget
+ pageTypes:
+ - Form
+ - List
+ - Assistant
+ components:
+ - Button, TextField, Textarea
+ - Select (dropdown), Checkbox, Radio
+ - Date/datetime, Fields with custom formatting
+ - Sublist (data grid), Group/Tab organization
+ rendering: Server-side to HTML
+
+ spas:
+ type: codedComponents
+ description: "Modern JSX-based Single Page Applications (2025.1+)"
+ framework: SuiteScript 2.1 + JSX
+ uiFramework: UIF (User Interface Framework)
+ components:
+ - Grids, buttons, inputs, modals
+ - Form handling, Layout components
+ moduleSystem: ESM (ECMAScript Modules)
+ tools: SuiteCloud Development Framework (SDF)
+
+sdk:
+ suiteScript: "N/ui/serverWidget, N/record"
+ spas: "@netsuite/uif"
+ devTools: SuiteCloud Developer Assistant (AI-powered)
+
+constraints:
+ - Customization limited to form layout/visibility
+ - SuiteScript: Server-side rendering, client interaction via Client Scripts
+ - SPAs require SuiteScript 2.1 (not backward compatible with 2.0)
+ - Module system migration required (ESM for SPAs vs RequireJS for older code)
+```
+
+---
+
+## Summary by Extension Type
+
+```
+┌───────────────────────────────────────────────────────────────────────────────────────┐
+│ EXTENSION TYPE DISTRIBUTION │
+├───────────────────────────────────────────────────────────────────────────────────────┤
+│ │
+│ JSON RESPONSE CODED COMPONENTS IFRAME EMBEDDED SDK AGENT UI │
+│ ────────────── ───────────────── ────── ──────────── ──────── │
+│ • Google Workspace • HubSpot UI Ext • Front • Stripe • MCP Apps │
+│ • Asana • Salesforce LWC • Zendesk • Plaid • Copilot │
+│ • Gorgias • Canva • Freshdesk • PayPal Studio │
+│ • Pipedrive • Shopify • Intercom • Auth0 │
+│ • Slack Block Kit • Monday.com • Figma • Calendly │
+│ • Adaptive Cards • Zendesk Garden • Salesforce • Typeform │
+│ • Zapier (fields) • Zapier Interfaces Canvas │
+│ • Make.com (RPC) • NetSuite SPAs │
+│ • Power Automate • NetSuite Script │
+│ • NetSuite Custom │
+│ │
+│ ════════════════════════════════════════════════════════════════════════════════ │
+│ Platform renders Platform runs Developer app Platform SDK AI agent │
+│ from JSON developer code in iframe in dev's app drives UI │
+│ │
+└───────────────────────────────────────────────────────────────────────────────────────┘
+```
diff --git a/specs/fenestra/ISSUES.md b/specs/fenestra/ISSUES.md
new file mode 100644
index 0000000..cfb4262
--- /dev/null
+++ b/specs/fenestra/ISSUES.md
@@ -0,0 +1,290 @@
+# Fenestra Specification - Known Issues & Roadmap
+
+This document captures findings from adversarial review of the v0.1.0-draft specification.
+
+## Summary of Findings
+
+| Category | Critical | High | Medium | Low |
+|----------|----------|------|--------|-----|
+| Platform Ecosystem | 3 | 4 | 3 | 3 |
+| MCP/JSON Forms Integration | 9 | 7 | 4 | 0 |
+| Policy Edge Cases | 6 | 6 | 6 | 2 |
+| Web Standards Mapping | 5 | 4 | 4 | 3 |
+
+---
+
+## Critical Issues (Must Fix for v0.2)
+
+### 1. Declarative/JSON UI Patterns Not Supported
+
+**Problem**: Cannot describe platforms using JSON-based UI (Slack Block Kit, Discord, Microsoft Adaptive Cards).
+
+**Platforms affected**: Slack, Discord, Microsoft Teams, Zoom Apps
+
+**Required addition**:
+```yaml
+ComponentDefinitionStyle:
+ enum:
+ - sdkImport # Current: import { Button } from '@sdk'
+ - jsonPayload # NEW: {"type": "button", "text": "..."}
+ - htmlTemplate # NEW:
+ - dsl # NEW: Custom domain-specific language
+```
+
+### 2. Mobile SDK Ecosystems Completely Missing
+
+**Problem**: No support for iOS/Android native platforms.
+
+**Required additions**:
+- Package managers: CocoaPods, Swift Package Manager, Android AAR, Flutter
+- Platform field on SDK: web, ios, android, desktop, cli
+- Language field: swift, kotlin, dart
+
+### 3. No Internationalization/Localization Support
+
+**Problem**: Zero support for RTL layouts, translations, or locale-specific components.
+
+**Required addition**: `I18nSupport` schema with locales, RTL, and translation keys.
+
+### 4. MCP Apps Integration Superficial
+
+**Problem**: `MCPAppsIntegration` lacks:
+- UI Resource schema (how to declare UI in server manifests)
+- Template definitions (form structure, layout, validation)
+- Tool-to-UI bindings (connecting tools to UI surfaces)
+- User consent mechanism for UI-initiated tool calls
+- Bidirectional JSON-RPC communication details
+
+### 5. JSON Forms Integration Incomplete
+
+**Problem**: `JSONFormsIntegration` lacks:
+- UI Schema structure (layouts, rules, options)
+- Custom renderer specification (tester functions, ranking)
+- Array control support (add/remove/reorder)
+- Validation and error display patterns
+- Categorization support (tabs, accordions, wizards)
+
+### 6. AI Agent Interaction Not Addressed
+
+**Problem**: Spec mentions AI agents but provides zero mechanisms for:
+- UI capability discovery by agents
+- Dynamic UI rendering from conversation context
+- User response handling and tool parameter collection
+
+### 7. Arazzo Integration Missing
+
+**Problem**: Spec mentions Arazzo but has no schema for:
+- Workflow step to UI binding
+- Form submission as workflow input
+- UI feedback on workflow progress
+
+### 8. Compliance Requirements Missing
+
+**Problem**: No way to express:
+- Accessibility standards (WCAG AA/AAA, Section 508)
+- Security certifications (SOC2, HIPAA, PCI-DSS, FedRAMP)
+- Privacy regulations (GDPR, CCPA, COPPA)
+- Data residency requirements
+
+### 9. ARIA Coverage Insufficient
+
+**Problem**: Single `ariaRole` field cannot express:
+- ARIA states and properties (49 attributes)
+- Composite patterns (combobox, tree, menu)
+- Live region announcements
+- APG pattern references
+
+---
+
+## High Priority Issues (v0.2 or v0.3)
+
+### 10. Theming System Underdeveloped
+
+**Problem**: Only `designTokensProvided: boolean`, no:
+- Dark/light mode specification
+- Theme token schema (colors, spacing, typography)
+- CSS custom properties integration
+
+### 11. Heavy React Bias
+
+**Problem**: Spec assumes React. Missing support for:
+- Vue/Angular/Svelte/Solid
+- CSS-only libraries (Mirotone)
+- No-code/low-code builders
+- Framework-agnostic patterns
+
+### 12. Hybrid Component Requirements
+
+**Problem**: Binary required/optional doesn't capture:
+- Per-category requirements (SDK for forms, custom for charts)
+- Per-extension-point requirements
+- Feature-tier requirements
+
+### 13. Publishing Tier Complexity
+
+**Problem**: Only private/public/marketplace tiers. Missing:
+- Beta/early access programs
+- Partner tier hierarchies
+- Regional/geographic policies
+- Industry-specific tiers
+
+### 14. Review Workflow Complexity
+
+**Problem**: Simple boolean flags can't express:
+- Multi-stage review pipelines
+- Parallel vs sequential reviews
+- Conditional review requirements
+- Component-level vs app-level review
+
+### 15. CSS Layout Patterns Missing
+
+**Problem**: No CSS layout information:
+- Flexbox/Grid assumptions
+- Responsive breakpoints
+- Container query support
+- Design token exposure
+
+### 16. Form Semantics Missing
+
+**Problem**: No form participation semantics:
+- HTML5 constraint validation API
+- FormData integration
+- Autocomplete/autofill support
+
+---
+
+## Medium Priority Issues (v0.3+)
+
+### 17. Versioning and Deprecation Tracking
+
+**Problem**: Simple `deprecated: boolean` and `since: string`. Need:
+- Sunset dates
+- Migration guides
+- Breaking change documentation
+- Version compatibility matrix
+
+### 18. Browser Extension Patterns
+
+**Problem**: Missing extension point types:
+- popup, sidepanel, devtools, contentScript
+
+### 19. Event Model Underdeveloped
+
+**Problem**: Simple event schema lacks:
+- DOM event equivalents
+- Event bubbling/composition
+- Touch/gesture events
+- Keyboard event expectations
+
+### 20. Custom Component Nuances
+
+**Problem**: Binary allowed/not-allowed. Need:
+- Wrapper requirements
+- Use-case-specific allowances
+- Approved third-party library lists
+
+### 21. Time-Based Policies
+
+**Problem**: No time dimension:
+- Deprecation timelines
+- Migration windows
+- Feature flag lifecycles
+- Policy version transitions
+
+---
+
+## Roadmap
+
+### v0.2.0 - Core Completeness
+- [ ] Add `ComponentDefinitionStyle` for JSON/declarative UI
+- [ ] Add `I18nSupport` schema
+- [ ] Expand `MCPAppsIntegration` with resource/template/binding schemas
+- [ ] Expand `JSONFormsIntegration` with UI schema/validation/renderers
+- [ ] Add `ArazzoIntegration` schema
+- [ ] Add `ComplianceRequirements` schema
+- [ ] Expand ARIA to include states, properties, and composite patterns
+
+### v0.3.0 - Policy Maturity
+- [ ] Add granular `ComponentRequirementPolicy` (per-category, per-extension-point)
+- [ ] Expand `CustomComponentPolicy` with approved libraries, wrapper requirements
+- [ ] Add `ReviewWorkflow` schema with multi-stage, conditional logic
+- [ ] Add `PublishingTier` hierarchy (beta, partner levels, regional)
+- [ ] Add `LifecyclePolicy` for time-based policies
+
+### v0.4.0 - Web Standards Depth
+- [ ] Expand `WebStandardMapping` with multi-element structures
+- [ ] Add `CSSLayoutPattern` schema
+- [ ] Add `FormSemantics` schema
+- [ ] Expand event model with DOM equivalents
+- [ ] Add mobile platform equivalents
+
+### v1.0.0 - Production Ready
+- [ ] Full cross-platform support (web, iOS, Android, desktop)
+- [ ] AI agent interaction mechanisms
+- [ ] Tooling for validation and code generation
+- [ ] Reference implementations for major platforms
+
+---
+
+## Required Tooling
+
+### Spec Validator (Critical - Required for OAI Submission)
+
+A reference implementation that validates Fenestra documents:
+
+```bash
+# Validate a Fenestra spec
+fenestra validate ./hubspot.fenestra.yaml
+
+# Output
+✓ Schema valid
+✓ Required fields present
+✓ SDK references resolved
+✓ Component bindings valid
+✗ Warning: Component 'CustomButton' not in catalog
+```
+
+**Requirements**:
+- JSON Schema validation against `fenestra-spec.yaml`
+- Reference resolution ($ref support)
+- Custom validation rules (SDK exists, components match)
+- CLI interface
+- Programmatic API (JavaScript/TypeScript)
+
+**Repository**: `fenestra-tools` or part of main spec repo
+
+### Code Generator (High Priority)
+
+Generate SDK bindings and types from Fenestra specs:
+
+```bash
+# Generate TypeScript types
+fenestra generate --platform hubspot --output ./src/types
+
+# Generate React component stubs
+fenestra generate --platform hubspot --template react --output ./src/components
+```
+
+### Documentation Generator (Medium Priority)
+
+Auto-generate developer docs from specs:
+
+```bash
+fenestra docs --platform hubspot --output ./docs
+```
+
+### IDE Extension (Medium Priority)
+
+VS Code extension with:
+- Autocomplete for Fenestra YAML
+- Schema validation
+- Component catalog browsing
+- Quick navigation to SDK docs
+
+---
+
+## See Also
+
+- [SUBMISSION.md](./SUBMISSION.md) - OAI submission guide
+- [PLATFORMS.md](./PLATFORMS.md) - Target platform list
+- [TASKS.md](./TASKS.md) - Development progress
diff --git a/specs/fenestra/MAINTAINERS.md b/specs/fenestra/MAINTAINERS.md
new file mode 100644
index 0000000..da75144
--- /dev/null
+++ b/specs/fenestra/MAINTAINERS.md
@@ -0,0 +1,55 @@
+# Fenestra Specification Maintainers
+
+This document lists the maintainers of the Fenestra Specification.
+
+## Current Maintainers
+
+| Name | GitHub | Organization | Role |
+|------|--------|--------------|------|
+| TBD | @TBD | Frigg Framework | Lead Maintainer |
+
+## Maintainer Responsibilities
+
+Maintainers are responsible for:
+
+- Reviewing and merging pull requests
+- Triaging issues
+- Ensuring specification quality and consistency
+- Facilitating working group discussions
+- Representing the specification at conferences and events
+- Coordinating with the OpenAPI Initiative
+
+## Becoming a Maintainer
+
+New maintainers are nominated by existing maintainers based on:
+
+- Sustained contributions to the specification
+- Deep understanding of the problem space
+- Commitment to the project's goals
+- Positive community interactions
+
+## Emeritus Maintainers
+
+Maintainers who are no longer active but made significant contributions:
+
+| Name | GitHub | Contributions |
+|------|--------|---------------|
+| (none yet) | | |
+
+## Working Group
+
+The Fenestra Working Group meets regularly to discuss specification development. Meeting notes and recordings are available in the repository.
+
+### Joining the Working Group
+
+To join the working group:
+
+1. Attend a public meeting
+2. Introduce yourself and your interest
+3. Request to be added to the meeting invites
+
+## Contact
+
+- **GitHub Issues**: For specification feedback and bug reports
+- **GitHub Discussions**: For questions and ideas
+- **Email**: fenestra-wg@friggframework.org (TBD)
diff --git a/specs/fenestra/PLATFORMS.md b/specs/fenestra/PLATFORMS.md
new file mode 100644
index 0000000..dae45c1
--- /dev/null
+++ b/specs/fenestra/PLATFORMS.md
@@ -0,0 +1,278 @@
+# Platform UI Ecosystems - Research List
+
+> Working document for tracking platforms that could have Fenestra specifications.
+> Use this to spawn subagents for building individual platform specs.
+
+**Total Platforms Identified**: 100+
+
+---
+
+## Priority Tiers
+
+### Tier 1: High Priority (Build specs first)
+Popular platforms with well-documented extension ecosystems.
+
+| Platform | Category | Extension Type | Dev Docs | Status |
+|----------|----------|----------------|----------|--------|
+| HubSpot | CRM | Coded Components | [Link](https://developers.hubspot.com/docs/platform/ui-extensions-overview) | ✅ Example exists |
+| Slack | Collaboration | JSON Response | [Link](https://docs.slack.dev/block-kit/) | ⏳ Pending |
+| Salesforce | CRM | Coded Components | [Link](https://developer.salesforce.com) | ⏳ Pending |
+| Figma | Design | Iframe | [Link](https://developers.figma.com/docs/plugins/) | ⏳ Pending |
+| Canva | Design | Coded Components | [Link](https://www.canva.dev/docs/apps/app-ui-kit/) | ⏳ Pending |
+| Stripe | Payments | Embedded SDK | [Link](https://docs.stripe.com) | ⏳ Pending |
+| Shopify | E-commerce | Coded Components | [Link](https://shopify.dev) | ⏳ Pending |
+| VS Code | Dev Tools | Coded Components | [Link](https://code.visualstudio.com/api) | ⏳ Pending |
+| Zendesk | Support | Iframe + Coded | [Link](https://developer.zendesk.com) | ⏳ Pending |
+| Microsoft Teams | Collaboration | JSON (Adaptive Cards) | [Link](https://docs.microsoft.com/en-us/microsoftteams/platform/) | ⏳ Pending |
+| DocuSign | Document & Agreement | Embedded SDK + Extensions + Agent UI | [Link](https://developers.docusign.com) | ⏳ Pending |
+
+### Tier 2: Medium Priority
+Well-established platforms with good documentation.
+
+| Platform | Category | Extension Type | Dev Docs | Status |
+|----------|----------|----------------|----------|--------|
+| Miro | Design | Iframe + SDK | [Link](https://developers.miro.com) | ✅ Example exists |
+| Front | Support | Iframe | [Link](https://dev.frontapp.com) | ⏳ Pending |
+| Asana | Productivity | JSON + Iframe | [Link](https://developers.asana.com) | ⏳ Pending |
+| Monday.com | Productivity | Coded Components | [Link](https://developer.monday.com) | ⏳ Pending |
+| Notion | Productivity | Iframe | [Link](https://developers.notion.com) | ⏳ Pending |
+| Airtable | Productivity | Coded + JSON | [Link](https://airtable.com/developers) | ⏳ Pending |
+| Intercom | Support | JSON + Iframe | [Link](https://developers.intercom.com) | ⏳ Pending |
+| Freshdesk | Support | Iframe | [Link](https://developers.freshdesk.com) | ⏳ Pending |
+| PayPal | Payments | Embedded SDK | [Link](https://developer.paypal.com) | ⏳ Pending |
+| Plaid | Payments | Embedded SDK | [Link](https://plaid.com/docs/link/web/) | ⏳ Pending |
+
+### Tier 3: Lower Priority (Future)
+Smaller or more specialized platforms.
+
+---
+
+## Complete Platform List by Category
+
+### 1. CRM Platforms
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| Salesforce | Coded (LWC) + Iframe | [Link](https://developer.salesforce.com) | [AppExchange](https://appexchange.salesforce.com) | LWC, Canvas SDK |
+| HubSpot | Coded (React) + JSON | [Link](https://developers.hubspot.com) | [Marketplace](https://ecosystem.hubspotpartnerprogram.com) | @hubspot/ui-extensions |
+| Pipedrive | JSON + Iframe | [Link](https://developers.pipedrive.com) | [Marketplace](https://marketplace.pipedrive.com) | pipedrive-client |
+| Zoho CRM | Coded + Iframe | [Link](https://www.zoho.com/crm/developer) | [Marketplace](https://marketplace.zoho.com) | Zoho Creator SDK |
+| Microsoft Dynamics 365 | Coded (PCF) | [Link](https://docs.microsoft.com/dynamics365/) | [AppSource](https://appsource.microsoft.com) | PowerApps SDK |
+| Freshsales | JSON + Iframe | [Link](https://developers.freshworks.com) | [Marketplace](https://marketplace.freshworks.com) | freshworks-sdk |
+| Copper | JSON + Iframe | [Link](https://developer.copper.com) | [Integrations](https://www.copper.com/integrations) | Copper API |
+| Close | Iframe | [Link](https://developer.close.com) | [Marketplace](https://resources.close.io/marketplace) | Close API |
+| Insightly | JSON + Iframe | [Link](https://api.insightly.com) | [Marketplace](https://marketplace.insightly.com) | Insightly API |
+
+### 2. Productivity & Collaboration
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| Slack | JSON (Block Kit) | [Link](https://docs.slack.dev/block-kit/) | [App Directory](https://api.slack.com/apps) | @slack/bolt |
+| Microsoft Teams | JSON (Adaptive Cards) | [Link](https://docs.microsoft.com/microsoftteams/platform/) | [App Store](https://appsource.microsoft.com) | @microsoft/adaptivecards |
+| Notion | Iframe + Database | [Link](https://developers.notion.com) | [Integrations](https://www.notion.so/integrations) | @notionhq/client |
+| Coda | Coded (Packs) | [Link](https://coda.io/developers) | [Packs](https://coda.io/packs) | Coda SDK |
+| Airtable | Coded + JSON | [Link](https://airtable.com/developers) | [Marketplace](https://airtable.com/marketplace) | Airtable.js |
+| Monday.com | Coded (React) | [Link](https://developer.monday.com) | [Marketplace](https://monday.com/marketplace) | monday-sdk-js |
+| Asana | JSON + Iframe | [Link](https://developers.asana.com) | [App Directory](https://asana.com/apps) | Asana API |
+| ClickUp | JSON + Iframe | [Link](https://docs.clickup.com) | [Marketplace](https://clickup.com/marketplace) | ClickUp API |
+| Linear | Iframe + GraphQL | [Link](https://developers.linear.app) | [Integrations](https://linear.app/integrations) | Linear GraphQL |
+| Trello | Iframe (Power-Ups) | [Link](https://developers.trello.com) | [Marketplace](https://trello.com/app-marketplace) | Trello.js |
+| Jira | Iframe + Coded | [Link](https://developer.atlassian.com/cloud/jira) | [Marketplace](https://marketplace.atlassian.com) | Jira REST API |
+
+### 3. Design & Creative Tools
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| Figma | Iframe (Plugins) | [Link](https://developers.figma.com/docs/plugins/) | [Community](https://www.figma.com/community/plugins) | @figma/plugin-typings |
+| Canva | Coded (React 19) | [Link](https://www.canva.dev/docs/apps/app-ui-kit/) | [App Store](https://www.canva.com/developers/apps/) | @canva/app-ui-kit |
+| Miro | Iframe + Web SDK | [Link](https://developers.miro.com) | [Marketplace](https://miro.com/marketplace) | miro-js-sdk |
+| Adobe Express | Iframe | [Link](https://developer.adobe.com/express/add-ons/docs/guides/) | [Add-ons](https://exchange.adobe.com) | Adobe UXP |
+| Sketch | Iframe (Plugins) | [Link](https://developer.sketch.com) | [Plugins](https://www.sketch.com/extensions/plugins/) | Sketch Plugin API |
+| Framer | Iframe + Coded | [Link](https://framer.com/developers) | [Marketplace](https://www.framer.com/marketplace) | Framer API |
+
+### 4. Customer Support
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| Zendesk | Iframe + Coded | [Link](https://developer.zendesk.com) | [Marketplace](https://www.zendesk.com/marketplace/) | ZAFClient |
+| Freshdesk | Iframe | [Link](https://developers.freshdesk.com) | [Marketplace](https://marketplace.freshworks.com) | Freshdesk App SDK |
+| Intercom | JSON + Iframe | [Link](https://developers.intercom.com) | [App Store](https://www.intercom.com/help/en/app-store) | @intercom/messenger-js-sdk |
+| Front | Iframe | [Link](https://dev.frontapp.com) | [Integrations](https://frontapp.com/integrations) | @frontapp/plugin-sdk |
+| Gorgias | JSON + Iframe | [Link](https://developers.gorgias.com) | [Marketplace](https://www.gorgias.com/integrations) | Gorgias SDK |
+| Help Scout | Iframe | [Link](https://developer.helpscout.com) | [Integrations](https://www.helpscout.com/integrations/) | Help Scout API |
+| Crisp | Iframe | [Link](https://docs.crisp.chat/api/) | [App Store](https://crisp.chat/en/integrations/) | Crisp API |
+| Drift | Iframe | [Link](https://developer.drift.com) | [Marketplace](https://www.drift.com/integrations) | Drift Embed SDK |
+| LiveChat | Iframe | [Link](https://developers.livechat.com) | [Integrations](https://www.livechat.com/integrations/) | LiveChat API |
+
+### 5. E-commerce
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| Shopify | Coded (Web Components) | [Link](https://shopify.dev) | [App Store](https://apps.shopify.com) | Shopify App Bridge |
+| BigCommerce | Iframe + Coded | [Link](https://developer.bigcommerce.com) | [Marketplace](https://www.bigcommerce.com/apps/) | BigCommerce API |
+| WooCommerce | Coded (PHP) | [Link](https://woocommerce.com/developer/) | [Marketplace](https://woocommerce.com/products/) | WooCommerce REST API |
+| Magento | Coded (PHP/XML) | [Link](https://developer.adobe.com/commerce) | [Marketplace](https://marketplace.magento.com) | Magento Extension Framework |
+| Wix | Iframe + Coded | [Link](https://dev.wix.com) | [App Market](https://www.wix.com/app-market) | Wix APIs |
+| PrestaShop | Coded (PHP) | [Link](https://devdocs.prestashop.com) | [Marketplace](https://addons.prestashop.com) | PrestaShop Module API |
+
+### 6. Developer Tools
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| GitHub | Iframe (Apps) | [Link](https://docs.github.com/developers) | [Marketplace](https://github.com/marketplace) | GitHub REST/GraphQL, Probot |
+| GitLab | Iframe + Coded | [Link](https://docs.gitlab.com/ee/api/) | [Integrations](https://about.gitlab.com/integrations/) | GitLab API |
+| VS Code | Coded (TypeScript) | [Link](https://code.visualstudio.com/api) | [Marketplace](https://marketplace.visualstudio.com/) | VS Code Extension API |
+| JetBrains IDEs | Coded (Kotlin/Java) | [Link](https://plugins.jetbrains.com/docs) | [Marketplace](https://plugins.jetbrains.com) | IntelliJ Plugin SDK |
+| Raycast | Coded (React/TS) | [Link](https://developers.raycast.com) | [Store](https://www.raycast.com/store) | Raycast API |
+
+### 7. Marketing & Analytics
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| Mixpanel | Iframe + JSON | [Link](https://developer.mixpanel.com) | [Integrations](https://mixpanel.com/integrations/) | Mixpanel SDK |
+| Amplitude | Iframe + JSON | [Link](https://developers.amplitude.com) | [Integrations](https://amplitude.com/integrations) | Amplitude SDK |
+| Segment | JSON | [Link](https://segment.com/docs/connections/) | [Catalog](https://segment.com/catalog/) | Segment API |
+| Mailchimp | JSON + Iframe | [Link](https://mailchimp.com/developer/) | [Integrations](https://mailchimp.com/integrations/) | Mailchimp API |
+| Marketo | Iframe + JSON | [Link](https://developers.marketo.com) | [Partners](https://business.adobe.com/products/marketo/partners.html) | Marketo REST API |
+| Klaviyo | Embedded SDK + JSON | [Link](https://developers.klaviyo.com) | [Integrations](https://www.klaviyo.com/integrations) | klaviyo-api, Klaviyo.js |
+| Braze | Embedded SDK + JSON | [Link](https://www.braze.com/docs/developer_guide) | [Partners](https://www.braze.com/partners) | @braze/web-sdk, Braze Swift SDK |
+
+### 8. Finance & Payments
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| Stripe | Embedded SDK | [Link](https://docs.stripe.com) | Limited | @stripe/stripe-js |
+| PayPal | Embedded SDK | [Link](https://developer.paypal.com) | [Integrations](https://www.paypal.com/integrations) | PayPal JS SDK |
+| Plaid | Embedded SDK | [Link](https://plaid.com/docs/link/web/) | [Partners](https://plaid.com/solutions/partnerships/) | react-plaid-link |
+| Square | Embedded SDK | [Link](https://developer.squareup.com) | [Marketplace](https://squareup.com/appmarketplace) | Square Web Payments SDK |
+| QuickBooks | Iframe + JSON | [Link](https://developer.intuit.com) | [App Center](https://appcenter.intuit.com) | QuickBooks REST API |
+| Xero | Iframe + JSON | [Link](https://developer.xero.com) | [App Store](https://www.xero.com/appstore/) | Xero API |
+
+### 9. HR & Recruiting
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| Workday | Iframe + Coded | [Link](https://community.workday.com) | [Marketplace](https://www.workday.com/marketplace.html) | Workday HCM API |
+| BambooHR | Iframe + JSON | [Link](https://developers.bamboohr.com) | [Integrations](https://www.bamboohr.com/integrations) | BambooHR REST API |
+| Greenhouse | Iframe + JSON | [Link](https://developers.greenhouse.io) | [Integrations](https://www.greenhouse.io/integrations) | Greenhouse Harvest API |
+| Lever | Iframe + JSON | [Link](https://hire.lever.co/developers) | [Integrations](https://www.lever.co/integrations) | Lever API |
+| Gusto | Iframe + JSON | [Link](https://gusto.com/api) | [App Directory](https://gusto.com/integrations) | Gusto API |
+| Rippling | Iframe + Coded | [Link](https://developer.rippling.com) | [Extensions](https://www.rippling.com/integrations) | Rippling API |
+
+### 10. Workflow & Automation
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| Zapier | JSON + Coded | [Link](https://zapier.com/developer) | [App Store](https://zapier.com/apps) | @zapier/platform-sdk |
+| Make.com | JSON (RPC) | [Link](https://developers.make.com) | [Integrations](https://www.make.com/integrations) | Make API |
+| Power Automate | JSON (OpenAPI + Cards) | [Link](https://learn.microsoft.com/power-automate) | [AppSource](https://appsource.microsoft.com) | Adaptive Cards SDK |
+| n8n | JSON + Iframe | [Link](https://docs.n8n.io) | [Integrations](https://n8n.io/integrations) | n8n SDK |
+| Tray.io | JSON + Iframe | [Link](https://tray.io/documentation) | [Marketplace](https://tray.io/integrations) | Tray iPaaS API |
+| Workato | JSON + Iframe | [Link](https://docs.workato.com) | [Connectors](https://docs.workato.com/connectors.html) | Workato SDK |
+
+### 11. ERP & Business Systems
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| NetSuite | Coded (SuiteScript) + SPAs | [Link](https://docs.oracle.com/netsuite) | [Marketplace](https://www.netsuite.com/portal/marketplace/apps) | SuiteScript 2.x, @netsuite/uif |
+| SAP S/4HANA | Coded (SAPUI5) | [Link](https://developers.sap.com) | [SAP Store](https://store.sap.com) | SAPUI5 SDK |
+| Oracle ERP | Iframe + APEX | [Link](https://docs.oracle.com) | [Marketplace](https://cloudmarketplace.oracle.com) | Oracle APEX |
+| Odoo | Coded (Python/XML) | [Link](https://www.odoo.com/documentation) | [App Store](https://apps.odoo.com) | Odoo Framework |
+
+### 12. Identity & Auth
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| Auth0 | Embedded SDK | [Link](https://auth0.com/docs) | [Marketplace](https://marketplace.auth0.com) | auth0-js, @auth0/auth0-react |
+| Okta | Embedded SDK | [Link](https://developer.okta.com) | [Integrations](https://www.okta.com/integrations/) | okta-auth-js |
+
+### 13. Scheduling & Calendar
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| Calendly | Embedded Widget | [Link](https://developer.calendly.com) | [Integrations](https://calendly.com/integrations) | Calendly API |
+| Cal.com | Embedded + Open Source | [Link](https://cal.com/docs) | [Marketplace](https://cal.com/marketplace) | Cal.com API |
+
+### 14. Forms & Surveys
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| Typeform | Embedded SDK | [Link](https://www.typeform.com/developers/) | [Integrations](https://www.typeform.com/integrations/) | @typeform/embed |
+| JotForm | Iframe | [Link](https://jotform.io/api/) | [Integrations](https://www.jotform.com/integrations) | JotForm API |
+| Tally | Iframe | [Link](https://tally.so/help) | [Integrations](https://tally.so/integrations) | Tally API |
+
+### 15. Video & Meetings
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| Zoom | Iframe + SDK | [Link](https://developers.zoom.us) | [Marketplace](https://marketplace.zoom.us) | Zoom SDK |
+| Loom | Embedded Widget | [Link](https://www.loom.com/developers) | Limited | Loom Embed SDK |
+| Daily.co | Embedded SDK | [Link](https://docs.daily.co) | [Marketplace](https://www.daily.co/marketplace) | Daily.co SDK |
+
+### 16. AI & ML Platforms
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| OpenAI | JSON + Plugins | [Link](https://platform.openai.com/docs) | [Plugin Store](https://openai.com/blog/plugins) | openai |
+| Anthropic | JSON (MCP) | [Link](https://docs.anthropic.com) | MCP ecosystem | @anthropic-ai/sdk |
+| Hugging Face | Iframe (Spaces) | [Link](https://huggingface.co/docs) | [Spaces](https://huggingface.co/spaces) | transformers |
+
+### 17. Documentation & CMS
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| Confluence | Iframe + Coded | [Link](https://developer.atlassian.com/cloud/confluence) | [Marketplace](https://marketplace.atlassian.com) | Confluence REST API |
+| Contentful | Iframe + JSON | [Link](https://www.contentful.com/developers/) | [App Framework](https://www.contentful.com/developers/docs/concepts/apps/) | @contentful/app-sdk |
+| WordPress | Coded (PHP) | [Link](https://developer.wordpress.org) | [Plugins](https://wordpress.org/plugins/) | WordPress Plugin API |
+
+### 18. Document & Agreement
+
+| Platform | Extension Type | Dev Docs | Marketplace | SDK |
+|----------|----------------|----------|-------------|-----|
+| DocuSign | Embedded SDK + Extensions + Agent UI | [Link](https://developers.docusign.com) | [App Center](https://www.docusign.com/partners/app-center) | @docusign/esign, Mobile SDKs, MCP Server |
+| Adobe Sign | Embedded SDK + Iframe | [Link](https://developer.adobe.com/document-services/docs/overview/) | [Exchange](https://exchange.adobe.com) | Adobe Sign API |
+| PandaDoc | Embedded SDK + Iframe | [Link](https://developers.pandadoc.com) | [Integrations](https://www.pandadoc.com/integrations/) | PandaDoc API |
+| HelloSign (Dropbox Sign) | Embedded SDK | [Link](https://developers.hellosign.com) | [Integrations](https://www.hellosign.com/integrations) | hellosign-sdk |
+| SignNow | Embedded SDK | [Link](https://docs.signnow.com) | [Integrations](https://www.signnow.com/integrations) | SignNow API |
+
+> **DocuSign Notes (2024-2025):**
+> - **Extension Apps**: JSON-based apps via Developer Console, distributed through App Center
+> - **Embedded Signing/Sending**: Embed signing ceremonies in your app via Focused View
+> - **1FE Micro-frontend**: Modular embedded DocuSign experiences
+> - **MCP Server**: AI integration with Claude, GitHub Copilot, ChatGPT (beta)
+> - **Maestro API**: Programmatic agreement workflow orchestration (GA 2025)
+
+---
+
+## Extension Type Distribution
+
+| Type | Count | Examples |
+|------|-------|----------|
+| **JSON Response** | ~22 | Slack, Asana, Zapier, Make.com, Power Automate |
+| **Coded Components** | ~28 | HubSpot, Canva, VS Code, Shopify, Monday.com |
+| **Iframe** | ~31 | Front, Zendesk, Figma, Miro, Freshdesk |
+| **Embedded SDK** | ~18 | Stripe, PayPal, Plaid, Auth0, DocuSign, PandaDoc, HelloSign |
+| **Agent UI** | ~9 | MCP Apps, Power Automate Copilot, DocuSign MCP |
+
+---
+
+## Usage
+
+To build a Fenestra spec for a platform:
+
+```bash
+# Spawn a subagent to research and build a spec
+# Example prompt:
+"Build a complete Fenestra specification for [Platform Name].
+Use the developer docs at [URL].
+Include all components, extension points, SDK bindings, and policies.
+Output as examples/[platform].fenestra.yaml"
+```
+
+---
+
+## See Also
+
+- [ECOSYSTEM-MAPPING.md](./ECOSYSTEM-MAPPING.md) - Detailed research on mapped platforms
+- [examples/](./examples/) - Existing Fenestra spec examples
+- [fenestra-spec.yaml](./fenestra-spec.yaml) - The specification schema
diff --git a/specs/fenestra/README.md b/specs/fenestra/README.md
new file mode 100644
index 0000000..b307851
--- /dev/null
+++ b/specs/fenestra/README.md
@@ -0,0 +1,194 @@
+# Fenestra Specification
+
+
+
+**Fenestra** (Latin for "window") is a specification for describing platform UI component ecosystems, SDK bindings, and UI rendering capabilities in a standardized, machine-readable format.
+
+## Specification Structure
+
+Fenestra uses a **modular architecture**: a Core specification plus optional Extensions. This mirrors the pattern used by other OAI specifications (OpenAPI + Overlay, Arazzo as a companion spec).
+
+| Specification | Objects | Purpose |
+|---------------|---------|---------|
+| [**Fenestra Core**](versions/core/0.1.0.md) | ~35 | Components, SDKs, Extension Points, Policies |
+| [**Agents Extension**](versions/extensions/agents/0.1.0.md) | ~18 | AI agent interaction (MCP, templates, permissions) |
+| [**Compliance Extension**](versions/extensions/compliance/0.1.0.md) | ~14 | Accessibility, security, privacy requirements |
+| [**I18n Extension**](versions/extensions/i18n/0.1.0.md) | ~9 | Internationalization capabilities |
+| [**Declarative Extension**](versions/extensions/declarative/0.1.0.md) | ~4 | JSON-based UI schemas (Block Kit, Adaptive Cards) |
+
+### Why Modular?
+
+- **Core is comparable to OpenAPI** (~35 objects vs OpenAPI's 30)
+- **Extensions are optional** - platforms adopt what's relevant
+- **Independent versioning** - agents can evolve faster than core
+- **Fills documentation gaps** - provides vocabulary for things platforms *should* document but often don't (compliance, i18n)
+
+### JSON Schemas
+
+| Schema | Purpose |
+|--------|---------|
+| [fenestra-core.schema.json](schemas/core/v0.1/fenestra-core.schema.json) | Validate Core documents |
+| [fenestra-agents.schema.json](schemas/extensions/agents/v0.1/fenestra-agents.schema.json) | Validate Agents extension |
+| [fenestra-compliance.schema.json](schemas/extensions/compliance/v0.1/fenestra-compliance.schema.json) | Validate Compliance extension |
+| [fenestra-i18n.schema.json](schemas/extensions/i18n/v0.1/fenestra-i18n.schema.json) | Validate I18n extension |
+| [fenestra-declarative.schema.json](schemas/extensions/declarative/v0.1/fenestra-declarative.schema.json) | Validate Declarative extension |
+
+## Overview
+
+Modern platforms (HubSpot, Salesforce, Slack, Figma, Stripe, etc.) provide UI extension points with varying degrees of flexibility. Fenestra standardizes the description of:
+
+**Core Capabilities:**
+- **Component Catalogs** - What UI components a platform provides
+- **SDK Bindings** - How to import and use components from platform SDKs
+- **Extension Points** - Where UI can be injected in the host platform
+- **Policies** - Component requirements, custom component rules, publishing constraints
+- **Rendering Engines** - How UI definitions translate to rendered interfaces
+
+**Extension Capabilities:**
+- **Agent Interaction** - How AI agents invoke UI (MCP protocol, templates, permissions)
+- **Compliance** - Accessibility (WCAG), security (SOC2), privacy (GDPR) requirements
+- **Internationalization** - Localization requirements, RTL support, translation mechanisms
+- **Declarative Schemas** - JSON-based UI patterns (Slack Block Kit, Adaptive Cards)
+
+## Quick Example
+
+```yaml
+fenestra: "0.1.0"
+info:
+ title: HubSpot UI Extensions
+ version: "1.0.0"
+platform:
+ name: HubSpot
+ documentation: https://developers.hubspot.com/docs/platform/ui-extensions-overview
+sdks:
+ hubspot-ui-extensions:
+ name: HubSpot UI Extensions SDK
+ packageManager: npm
+ package: "@hubspot/ui-extensions"
+policies:
+ componentRequirement:
+ level: required
+ scope: all
+ customComponents:
+ allowed: false
+extensionPoints:
+ - id: crm-sidebar
+ name: CRM Record Sidebar
+ type: sidebar
+ extensionType: codedComponents
+
+# Optional extensions:
+compliance:
+ accessibility:
+ platformStandard: "WCAG 2.1 AA"
+ security:
+ platformCertifications: ["SOC 2 Type II"]
+
+i18n:
+ platformSupport:
+ availableLocales: ["en", "es", "fr", "de"]
+
+agentInteraction:
+ protocols:
+ - name: mcp
+ version: "1.0"
+```
+
+## Repository Structure
+
+```
+fenestra/
+├── versions/
+│ ├── core/
+│ │ └── 0.1.0.md # Core specification
+│ └── extensions/
+│ ├── agents/0.1.0.md # Agents extension
+│ ├── compliance/0.1.0.md # Compliance extension
+│ ├── declarative/0.1.0.md # Declarative extension
+│ └── i18n/0.1.0.md # I18n extension
+├── schemas/
+│ ├── core/v0.1/ # Core JSON Schema
+│ └── extensions/
+│ ├── agents/v0.1/
+│ ├── compliance/v0.1/
+│ ├── declarative/v0.1/
+│ └── i18n/v0.1/
+├── examples/
+│ └── 0.1.0/ # Example documents
+├── tools/ # Validator CLI
+├── CONTRIBUTING.md
+├── MAINTAINERS.md
+└── README.md
+```
+
+## Relationship to Other Specifications
+
+Fenestra complements existing specifications:
+
+| Specification | Describes | Fenestra Relationship |
+|---------------|-----------|----------------------|
+| **OpenAPI** | REST API endpoints | Companion spec; APIs can reference Fenestra for UI responses |
+| **Arazzo** | API workflow sequences | Workflow steps can invoke Fenestra-described UI |
+| **MCP** | Model Context Protocol | Agents extension aligns with MCP Apps patterns |
+| **JSON Schema** | Data validation | Fenestra uses JSON Schema for component props |
+
+## Examples
+
+See the [examples](examples/0.1.0/) directory:
+
+- [hubspot.fenestra.yaml](examples/0.1.0/hubspot.fenestra.yaml) - HubSpot UI Extensions
+- [miro.fenestra.yaml](examples/0.1.0/miro.fenestra.yaml) - Miro Developer Platform
+- [mcp-apps.fenestra.yaml](examples/0.1.0/mcp-apps.fenestra.yaml) - MCP Apps Host
+
+## Tooling
+
+### Validator CLI
+
+```bash
+cd tools && npm install
+node bin/fenestra.js validate ../examples/0.1.0/hubspot.fenestra.yaml
+```
+
+### Planned Tooling
+
+- **Generator** - Generate integration scaffolding from specs
+- **Docs Generator** - Generate documentation from specs
+- **Visual Designer** - Design integrations with platform-aware UI
+
+## Use Cases
+
+1. **Code Generation** - Generate platform-specific integration code
+2. **Visual Designers** - Build design tools aware of platform constraints
+3. **Validation** - Verify integrations follow platform policies
+4. **Documentation** - Auto-generate consistent developer docs
+5. **AI Agents** - Enable AI to understand platform UI capabilities
+6. **Cross-Platform Portability** - Map components between platforms
+7. **Compliance Tracking** - Document accessibility/security requirements
+
+## Contributing
+
+We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
+
+## Governance
+
+- **Maintainers**: See [MAINTAINERS.md](MAINTAINERS.md)
+- **Target**: OpenAPI Initiative (Linux Foundation)
+
+## Related Resources
+
+### OAI Specifications
+- [OpenAPI Specification](https://spec.openapis.org/oas/latest.html)
+- [Arazzo Specification](https://spec.openapis.org/arazzo/latest.html)
+
+### Platform Documentation
+- [HubSpot UI Extensions](https://developers.hubspot.com/docs/platform/ui-extensions-overview)
+- [Slack Block Kit](https://api.slack.com/block-kit)
+- [MCP Protocol](https://modelcontextprotocol.io/)
+
+## License
+
+Licensed under the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0).
+
+---
+
+**Fenestra** is designed for submission to the [OpenAPI Initiative](https://www.openapis.org/), a Linux Foundation Collaborative Project.
diff --git a/specs/fenestra/SUBMISSION.md b/specs/fenestra/SUBMISSION.md
new file mode 100644
index 0000000..9157a89
--- /dev/null
+++ b/specs/fenestra/SUBMISSION.md
@@ -0,0 +1,214 @@
+# Submitting Fenestra to the OpenAPI Initiative
+
+> Guide for submitting Fenestra as an OAI companion specification.
+
+---
+
+## Overview
+
+**Target**: OpenAPI Initiative (OAI), a Linux Foundation Collaborative Project
+
+**Model**: Companion specification (like Arazzo, Overlay)
+
+**Timeline**: 12-24 months from proposal to v1.0.0 release
+
+---
+
+## Spec Family Positioning
+
+```
+OpenAPI Specification → Describes REST APIs
+├── Arazzo → Describes API Workflows
+├── Overlay → Augments OpenAPI documents
+└── Fenestra → Describes Platform UI Extensibility ← NEW
+```
+
+**Elevator Pitch**:
+> "Just as Arazzo extends OpenAPI to describe workflows, Fenestra extends the ecosystem to describe UI component ecosystems. HubSpot, Canva, Slack, and Stripe struggle to document their platform UI constraints in a standardized way. Fenestra solves this."
+
+---
+
+## Required Documents
+
+### Before Proposal
+
+| Document | Status | Notes |
+|----------|--------|-------|
+| Specification schema | ✅ Done | `fenestra-spec.yaml` |
+| README with use cases | ✅ Done | 8 use cases documented |
+| Platform examples | 🔶 Partial | Need 5+ complete specs |
+| JSON Schema validator | ❌ Needed | Reference implementation |
+| GOVERNANCE.md | ❌ Needed | Copy OAI pattern |
+| CONTRIBUTING.md | ❌ Needed | Contribution guidelines |
+
+### For Working Group Formation
+
+| Document | Status | Notes |
+|----------|--------|-------|
+| Working group charter | ❌ Needed | Define scope and goals |
+| Committed participants list | ❌ Needed | 2-3 organizations minimum |
+| Development roadmap | 🔶 Partial | See TASKS.md |
+| Reference implementation | ❌ Needed | CLI validator + generator |
+
+---
+
+## Working Group Requirements
+
+### Do We Need One?
+
+**Yes** - OAI specs are developed by Special Interest Groups (SIGs).
+
+### Minimum Requirements
+
+- **Core contributors**: 3-5 active people
+- **Organizations**: 2-3 different companies
+- **Platform vendor**: At least 1 willing to provide test specs
+- **Membership fees**: None for technical participation
+
+### Formation Process
+
+1. Present proposal to OAI community
+2. Get TSC (Technical Steering Committee) interest
+3. Form SIG with charter
+4. Request `OAI/Fenestra-Specification` repository
+5. Begin public development
+
+---
+
+## Submission Process
+
+### Phase 1: Foundation (Months 1-2)
+
+- [ ] Finalize spec v0.2.0
+- [ ] Create 5+ complete platform examples
+- [ ] Build reference implementation (validator CLI)
+- [ ] Add GOVERNANCE.md and CONTRIBUTING.md
+- [ ] Identify 2-3 committed organizations
+
+### Phase 2: Community Engagement (Months 2-4)
+
+- [ ] Contact OAI: contact@openapis.org
+- [ ] Join OAI Slack workspace
+- [ ] Present at OAI TSC meeting (weekly, open to public)
+- [ ] Post in GitHub discussions
+- [ ] Attend apidays or similar conference
+
+### Phase 3: SIG Formation (Months 4-6)
+
+- [ ] Formal proposal to OAI Business Governing Board
+- [ ] Working group charter approved
+- [ ] `OAI/Fenestra-Specification` repo created
+- [ ] Weekly SIG meetings begin
+- [ ] Public development starts
+
+### Phase 4: Development (Months 6-18)
+
+- [ ] Iterate on spec based on feedback
+- [ ] Build tooling ecosystem (validators, generators, IDE plugins)
+- [ ] Get platform vendors to validate specs
+- [ ] Grow contributor base
+
+### Phase 5: Release (Months 18-24)
+
+- [ ] TSC review of v1.0.0-rc.1
+- [ ] Implementers' Draft testing period (3-6 months)
+- [ ] Address feedback, fix issues
+- [ ] TSC approval of v1.0.0
+- [ ] Announcement at apidays conference
+
+---
+
+## Governance Structure
+
+```
+Community Proposal → GitHub Issues/Discussions
+ ↓
+ Working Group / SIG Development
+ ↓
+ TSC Technical Review (Weekly)
+ ↓
+ Consensus achieved? → YES → Approved
+ ↓ NO
+ Escalate to Technical Oversight Board
+```
+
+### Key Bodies
+
+| Body | Role |
+|------|------|
+| **TSC** | Technical decisions, spec approval |
+| **BGB** | Business strategy, budget |
+| **SIG** | Day-to-day spec development |
+| **Linux Foundation** | Legal, infrastructure |
+
+---
+
+## Tooling Requirements
+
+### Minimum for Proposal
+
+1. **Validator CLI**
+ ```bash
+ fenestra validate ./hubspot.fenestra.yaml
+ ```
+
+2. **JSON Schema**
+ - Machine-readable schema for spec validation
+ - Can use the existing `fenestra-spec.yaml`
+
+### Recommended for 1.0.0
+
+1. **Code generators**
+ - Generate SDK bindings from spec
+ - Generate TypeScript types
+ - Generate documentation
+
+2. **IDE extensions**
+ - VS Code extension with autocomplete
+ - Schema validation in editor
+
+3. **Documentation generator**
+ - Auto-generate developer docs from spec
+
+---
+
+## Key Contacts
+
+| Resource | URL |
+|----------|-----|
+| OAI Website | https://www.openapis.org/ |
+| OAI GitHub | https://github.com/OAI |
+| Contact Email | contact@openapis.org |
+| TSC Meetings | Check openapis.org calendar |
+| Arazzo (reference) | https://github.com/OAI/Arazzo-Specification |
+| Overlay (reference) | https://github.com/OAI/Overlay-Specification |
+
+---
+
+## Risks & Mitigation
+
+| Risk | Mitigation |
+|------|------------|
+| OAI declines | Show real platform use cases, get vendor endorsements |
+| Long timeline | Build adoption while in draft, publish 0.x versions |
+| Small market | Focus on high-value platforms, integrate with existing tools |
+| TSC requirements | Build contributor base first, TSC emerges naturally |
+
+---
+
+## Immediate Next Steps
+
+1. **Build validator CLI** - Reference implementation
+2. **Create 5 complete platform specs** - HubSpot, Slack, Stripe, Figma, Zendesk
+3. **Recruit working group** - Find 2-3 committed organizations
+4. **Draft proposal** - Executive summary for OAI leadership
+5. **Contact OAI** - Send proposal package
+
+---
+
+## See Also
+
+- [README.md](./README.md) - Spec overview and use cases
+- [PLATFORMS.md](./PLATFORMS.md) - Target platform list
+- [TASKS.md](./TASKS.md) - Development progress
+- [ISSUES.md](./ISSUES.md) - Known gaps to address
diff --git a/specs/fenestra/TASKS.md b/specs/fenestra/TASKS.md
new file mode 100644
index 0000000..ffe68d7
--- /dev/null
+++ b/specs/fenestra/TASKS.md
@@ -0,0 +1,77 @@
+# Fenestra Spec Development Tasks
+
+> **Note**: For detailed extension type descriptions, see [README.md](./README.md).
+> For visual diagrams, see [DIAGRAMS.md](./DIAGRAMS.md).
+> For platform research, see [ECOSYSTEM-MAPPING.md](./ECOSYSTEM-MAPPING.md).
+
+---
+
+## Tasks
+
+### Phase 1: Diagrams for Each Type
+- [x] Create diagram: JSON Response type (render flow)
+- [x] Create diagram: Coded Components type (render flow)
+- [x] Create diagram: Iframe type (render flow)
+- [x] Create diagram: Embedded SDK type (render flow)
+- [x] Create diagram: JS SDK interaction pattern
+- [x] Create diagram: Agent UI type (render flow)
+
+**Output**: [DIAGRAMS.md](./DIAGRAMS.md)
+
+### Phase 2: Map Real Ecosystems
+- [x] Google Workspace Apps → JSON Response
+- [x] Asana → JSON Response
+- [x] Gorgias → JSON Response
+- [x] Pipedrive Extensions → JSON Response (hybrid)
+- [x] Slack Block Kit → JSON Response
+- [x] Microsoft Adaptive Cards → JSON Response
+- [x] Salesforce LWC → Coded Components
+- [x] HubSpot UI Extensions → Coded Components
+- [x] Zendesk → Coded Components / Iframe (hybrid)
+- [x] Canva SDK Apps → Coded Components
+- [x] Shopify App Bridge → Coded Components
+- [x] Monday.com → Coded Components
+- [x] Front → Iframe
+- [x] Figma → Iframe
+- [x] Freshdesk → Iframe
+- [x] Intercom → Iframe
+- [x] Stripe Elements → Embedded SDK
+- [x] Plaid Link → Embedded SDK
+- [x] PayPal Buttons → Embedded SDK
+- [x] Auth0 Lock → Embedded SDK
+- [x] Calendly → Embedded SDK
+- [x] Typeform → Embedded SDK
+- [x] Zapier → JSON Response + Coded Components (hybrid) [Workflow]
+- [x] Make.com → JSON Response (RPC-driven) [Workflow]
+- [x] Power Automate → JSON Response (OpenAPI + Adaptive Cards) [Workflow]
+- [x] NetSuite → JSON Response + Coded Components (hybrid) [ERP]
+
+**Output**: [ECOSYSTEM-MAPPING.md](./ECOSYSTEM-MAPPING.md)
+
+### Phase 3: Update Spec Schema
+- [x] Add `extensionType` enum to spec
+- [x] Define JSON Response schema details
+- [x] Define Coded Components schema details
+- [x] Define Iframe schema details
+- [x] Define Embedded SDK schema details
+- [x] Add JS SDK exposure schema
+- [x] Define Agent UI schema details (AgentUIConfig, AgentUITemplate)
+
+### Phase 4: Create Example Documents
+- [ ] Example: JSON Response platform (Slack Block Kit)
+- [x] Example: Coded Components platform (HubSpot)
+- [ ] Example: Iframe platform (Front)
+- [ ] Example: Embedded SDK platform (Stripe)
+- [ ] Example: Hybrid platform (Pipedrive or Zendesk)
+- [x] Example: Agent UI platform (MCP Apps)
+
+---
+
+## Research & Findings
+
+See [ECOSYSTEM-MAPPING.md](./ECOSYSTEM-MAPPING.md) for detailed platform research.
+
+**Key decisions made:**
+- Hybrid platforms modeled at extension-point level (each point can have different type)
+- Embedded SDK = platform SDK in developer's app (Stripe Elements, Plaid Link)
+- Agent UI added as 5th type for MCP Apps pattern
diff --git a/specs/fenestra/examples/0.1.0/canva.fenestra.yaml b/specs/fenestra/examples/0.1.0/canva.fenestra.yaml
new file mode 100644
index 0000000..1c0e767
--- /dev/null
+++ b/specs/fenestra/examples/0.1.0/canva.fenestra.yaml
@@ -0,0 +1,840 @@
+# Fenestra Document: Canva Apps SDK
+#
+# Canva represents a strongly-recommended component approach with built-in
+# internationalization and comprehensive design system integration.
+
+fenestra: "0.1.0"
+
+info:
+ title: Canva Apps SDK Ecosystem
+ version: "1.0.0"
+ description: |
+ Canva's Apps SDK provides React-based components and APIs for building
+ apps that integrate seamlessly into the Canva design editor.
+
+ Key characteristics:
+ - App UI Kit components are strongly recommended for public apps
+ - Built-in i18n with free translation service for approved apps
+ - React 19 with comprehensive design system support
+ - Apps run in iframes embedded in the Canva editor
+
+platform:
+ name: Canva
+ vendor: Canva Pty Ltd
+ documentation: https://www.canva.dev/docs/apps/
+ appMarketplace: https://www.canva.com/your-apps/
+ designSystem: Canva Design System
+ designSystemUrl: https://www.figma.com/community/file/1314652421936534778
+
+sdks:
+ canva-app-ui-kit:
+ name: Canva App UI Kit
+ packageManager: npm
+ package: "@canva/app-ui-kit"
+ version: "^5.0.0"
+ repository: https://github.com/canva-sdks/canva-apps-sdk-starter-kit
+ documentation: https://www.canva.dev/docs/apps/app-ui-kit/
+ description: |
+ React-based component library designed for creating apps that emulate
+ Canva's look and feel. Built for accessibility, usability, and
+ cross-platform compatibility.
+ peerDependencies:
+ react: "^19.0.0"
+ exports:
+ # Layout Components
+ Box:
+ type: component
+ description: Generic container for layout
+ category: layout
+ Rows:
+ type: component
+ description: Vertical stack layout container
+ category: layout
+ Columns:
+ type: component
+ description: Horizontal layout container
+ category: layout
+ Column:
+ type: component
+ description: Individual column within Columns
+ category: layout
+ Grid:
+ type: component
+ description: Grid layout container
+ category: layout
+
+ # Action Components
+ Button:
+ type: component
+ description: Primary action button with variants
+ category: action
+ LinkButton:
+ type: component
+ description: Button styled as a link for in-app actions
+ category: action
+
+ # Input Components
+ TextInput:
+ type: component
+ description: Single-line text input field
+ category: input
+ MultilineInput:
+ type: component
+ description: Multi-line text input
+ category: input
+ NumberInput:
+ type: component
+ description: Numeric input field
+ category: input
+ DateInput:
+ type: component
+ description: Date picker input
+ category: input
+ Select:
+ type: component
+ description: Dropdown selection with support for descriptions and icons
+ category: input
+ CustomizableSelect:
+ type: component
+ description: Advanced select with customization options
+ category: input
+ Checkbox:
+ type: component
+ description: Single checkbox input
+ category: input
+ CheckboxGroup:
+ type: component
+ description: Group of related checkboxes
+ category: input
+ RadioGroup:
+ type: component
+ description: Radio button group for exclusive selection
+ category: input
+ Switch:
+ type: component
+ description: Toggle switch for boolean values
+ category: input
+ Slider:
+ type: component
+ description: Slider for numeric range selection
+ category: input
+ ColorSelector:
+ type: component
+ description: Color picker component
+ category: input
+ FileInput:
+ type: component
+ description: File upload input
+ category: input
+ FileInputItem:
+ type: component
+ description: Individual file item in FileInput
+ category: input
+ FormField:
+ type: component
+ description: Form field wrapper with label and validation
+ category: input
+
+ # Display Components
+ Text:
+ type: component
+ description: Text display with typography support
+ category: display
+ Title:
+ type: component
+ description: Section title/heading
+ category: display
+ Alert:
+ type: component
+ description: Alert/notification message
+ category: display
+ Badge:
+ type: component
+ description: Status badge indicator
+ category: display
+ Avatar:
+ type: component
+ description: User avatar display
+ category: display
+ AvatarGroup:
+ type: component
+ description: Group of user avatars
+ category: display
+ Pill:
+ type: component
+ description: Pill-shaped label
+ category: display
+ InputPill:
+ type: component
+ description: Interactive pill component for inputs
+ category: display
+ Swatch:
+ type: component
+ description: Color swatch display
+ category: display
+
+ # Card Components
+ HorizontalCard:
+ type: component
+ description: Horizontal layout card
+ category: card
+ ImageCard:
+ type: component
+ description: Card for displaying images
+ category: card
+ VideoCard:
+ type: component
+ description: Card for displaying videos
+ category: card
+ AudioCard:
+ type: component
+ description: Card for displaying audio content
+ category: card
+ EmbedCard:
+ type: component
+ description: Card for embedded content
+ category: card
+ TypographyCard:
+ type: component
+ description: Card for typography samples
+ category: card
+
+ # Overlay Components
+ Flyout:
+ type: component
+ description: Popup overlay component
+ category: overlay
+ FlyoutMenu:
+ type: component
+ description: Menu in a flyout overlay
+ category: overlay
+
+ # Organizational Components
+ Accordion:
+ type: component
+ description: Collapsible content sections
+ category: organizational
+ Carousel:
+ type: component
+ description: Carousel for scrolling through content
+ category: organizational
+ SegmentedControl:
+ type: component
+ description: Segmented control for tab-like selection
+ category: organizational
+
+ # Design System Utilities
+ AppUiProvider:
+ type: provider
+ description: Context provider for theme and i18n support
+ category: system
+
+ # Icons (selected examples)
+ PlusIcon:
+ type: icon
+ description: Plus icon
+ category: icon
+ SearchIcon:
+ type: icon
+ description: Search icon
+ category: icon
+
+ canva-design:
+ name: Canva Design API
+ packageManager: npm
+ package: "@canva/design"
+ documentation: https://www.canva.dev/docs/apps/integrating-canva/
+ description: |
+ Provides methods for interacting with the user's design, such as
+ creating elements and manipulating the canvas.
+ exports:
+ addPage:
+ type: function
+ description: Adds a page to the user's design
+ requestExport:
+ type: function
+ description: Exports the user's design as static files
+ addNativeElement:
+ type: function
+ description: Adds native Canva elements to the design
+ addAudioTrack:
+ type: function
+ description: Adds audio track to the design
+
+ canva-asset:
+ name: Canva Asset API
+ packageManager: npm
+ package: "@canva/asset"
+ documentation: https://www.canva.dev/docs/apps/integrating-canva/
+ description: |
+ Provides methods for working with assets such as image and video files,
+ including uploading to the user's media library.
+ exports:
+ upload:
+ type: function
+ description: Uploads assets to the user's media library
+
+ canva-platform:
+ name: Canva Platform Utilities
+ packageManager: npm
+ package: "@canva/platform"
+ documentation: https://www.canva.dev/docs/apps/integrating-canva/
+ description: |
+ Provides utility methods useful for a broad range of apps, including
+ opening external links and platform-level operations.
+ exports:
+ requestOpenExternalUrl:
+ type: function
+ description: Opens an external web page
+
+ canva-user:
+ name: Canva User API
+ packageManager: npm
+ package: "@canva/user"
+ documentation: https://www.canva.dev/docs/apps/integrating-canva/
+ description: |
+ Provides methods for accessing user data and authenticating users.
+ exports:
+ getUser:
+ type: function
+ description: Retrieves current user information
+ authenticate:
+ type: function
+ description: Authenticates user for external services
+
+ canva-error:
+ name: Canva Error Handling
+ packageManager: npm
+ package: "@canva/error"
+ documentation: https://www.canva.dev/docs/apps/integrating-canva/
+ description: |
+ Provides CanvaError class for standardized error handling.
+ exports:
+ CanvaError:
+ type: class
+ description: Standard error class for Canva apps
+
+ canva-i18n-kit:
+ name: Canva Internationalization Kit
+ packageManager: npm
+ package: "@canva/app-i18n-kit"
+ documentation: https://www.canva.dev/docs/apps/localization/
+ description: |
+ Provides internationalization utilities that integrate with react-intl
+ for app localization. Required for production apps.
+ peerDependencies:
+ react-intl: "^6.0.0"
+ exports:
+ initIntl:
+ type: function
+ description: Initializes internationalization for non-React contexts
+
+componentCatalog:
+ categories:
+ layout:
+ name: Layout
+ description: Components for organizing and structuring content
+ components: [Box, Rows, Columns, Column, Grid]
+
+ action:
+ name: Actions
+ description: Interactive elements for user actions
+ components: [Button, LinkButton]
+
+ input:
+ name: Form Inputs
+ description: Form input and control components
+ components:
+ - TextInput
+ - MultilineInput
+ - NumberInput
+ - DateInput
+ - Select
+ - CustomizableSelect
+ - Checkbox
+ - CheckboxGroup
+ - RadioGroup
+ - Switch
+ - Slider
+ - ColorSelector
+ - FileInput
+ - FormField
+
+ display:
+ name: Display
+ description: Components for showing information and status
+ components: [Text, Title, Alert, Badge, Avatar, AvatarGroup, Pill, InputPill, Swatch]
+
+ card:
+ name: Cards
+ description: Card components for various content types
+ components: [HorizontalCard, ImageCard, VideoCard, AudioCard, EmbedCard, TypographyCard]
+
+ overlay:
+ name: Overlays
+ description: Overlay and popup components
+ components: [Flyout, FlyoutMenu]
+
+ organizational:
+ name: Organizational
+ description: Components for organizing and navigating content
+ components: [Accordion, Carousel, SegmentedControl]
+
+ components:
+ Button:
+ name: Button
+ description: Primary action button with variant support
+ category: action
+ sdkBinding:
+ sdk: canva-app-ui-kit
+ export: Button
+ webStandardMapping:
+ htmlElement: button
+ ariaRole: button
+ semanticType: action
+ props:
+ variant:
+ type: string
+ enum: [primary, secondary, tertiary]
+ default: primary
+ onClick:
+ type: function
+ description: Click handler
+ disabled:
+ type: boolean
+ default: false
+ loading:
+ type: boolean
+ default: false
+ description: Shows loading state
+ variants:
+ - primary
+ - secondary
+ - tertiary
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ i18n:
+ supported: true
+ description: Button text can be localized using react-intl
+
+ FormField:
+ name: FormField
+ description: Form field wrapper that provides label, validation, and error display
+ category: input
+ sdkBinding:
+ sdk: canva-app-ui-kit
+ export: FormField
+ props:
+ label:
+ type: string
+ description: Field label
+ error:
+ type: string
+ description: Error message to display
+ description:
+ type: string
+ description: Helper text for the field
+ slots:
+ control:
+ description: The form control (input, select, etc.)
+ required: true
+ accessibility:
+ screenReaderSupport: true
+ i18n:
+ supported: true
+
+ Select:
+ name: Select
+ description: Dropdown selection component with rich option support
+ category: input
+ sdkBinding:
+ sdk: canva-app-ui-kit
+ export: Select
+ webStandardMapping:
+ htmlElement: select
+ ariaRole: combobox
+ semanticType: input
+ props:
+ options:
+ type: array
+ description: Array of option objects with value, label, description, disabled, and icon
+ value:
+ type: string
+ description: Currently selected value
+ onChange:
+ type: function
+ description: Change handler
+ placeholder:
+ type: string
+ description: Placeholder text
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ i18n:
+ supported: true
+
+ Text:
+ name: Text
+ description: Text display component with typography system integration
+ category: display
+ sdkBinding:
+ sdk: canva-app-ui-kit
+ export: Text
+ webStandardMapping:
+ htmlElement: span
+ semanticType: text
+ props:
+ variant:
+ type: string
+ description: Typography variant
+ size:
+ type: string
+ enum: [small, medium, large]
+ tone:
+ type: string
+ description: Color tone from design system
+ accessibility:
+ screenReaderSupport: true
+ i18n:
+ supported: true
+
+ Rows:
+ name: Rows
+ description: Vertical stack layout container with consistent spacing
+ category: layout
+ sdkBinding:
+ sdk: canva-app-ui-kit
+ export: Rows
+ webStandardMapping:
+ htmlElement: div
+ semanticType: container
+ props:
+ spacing:
+ type: string
+ description: Spacing between rows using design tokens
+ align:
+ type: string
+ enum: [start, center, end, stretch]
+ slots:
+ default:
+ description: Child elements to stack vertically
+ required: true
+
+ Columns:
+ name: Columns
+ description: Horizontal layout container with responsive column support
+ category: layout
+ sdkBinding:
+ sdk: canva-app-ui-kit
+ export: Columns
+ webStandardMapping:
+ htmlElement: div
+ semanticType: container
+ props:
+ spacing:
+ type: string
+ description: Spacing between columns
+ align:
+ type: string
+ enum: [start, center, end, stretch]
+ slots:
+ default:
+ description: Column components
+ required: true
+
+ ColorSelector:
+ name: ColorSelector
+ description: Color picker component integrated with Canva's color system
+ category: input
+ sdkBinding:
+ sdk: canva-app-ui-kit
+ export: ColorSelector
+ props:
+ color:
+ type: string
+ description: Currently selected color
+ onChange:
+ type: function
+ description: Color change handler
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+
+extensionPoints:
+ - id: side-panel
+ name: Side Panel
+ type: panel
+ extensionType: codedComponents
+ description: |
+ Main app interface displayed in the Canva editor's side panel.
+ This is the primary extension point for most apps.
+ supportedComponents:
+ - all
+ constraints:
+ responsive: true
+ darkModeSupport: required
+ mobileFriendly: recommended
+ context:
+ provides:
+ - currentDesign
+ - user
+ - theme
+ actions:
+ - addElement
+ - uploadAsset
+ - exportDesign
+
+ - id: object-panel
+ name: Object Panel
+ type: contextual-panel
+ extensionType: codedComponents
+ description: |
+ Contextual panel that appears when a user selects an element created
+ by the app. Useful for element-specific editing controls.
+ supportedComponents:
+ - all
+ constraints:
+ responsive: true
+ darkModeSupport: required
+ context:
+ provides:
+ - selectedElement
+ - currentDesign
+ - user
+ actions:
+ - updateElement
+ - deleteElement
+
+ - id: editor-overlay
+ name: Editor Overlay
+ type: overlay
+ extensionType: codedComponents
+ description: |
+ Full-screen overlay for immersive editing experiences, such as
+ image editing or advanced configuration interfaces.
+ supportedComponents:
+ - all
+ constraints:
+ fullScreen: true
+ darkModeSupport: required
+ context:
+ provides:
+ - targetElement
+ - currentDesign
+ - user
+ actions:
+ - broadcastMessage
+ - closeOverlay
+ - saveChanges
+ documentation: https://www.canva.dev/docs/apps/creating-image-overlays/
+
+policies:
+ componentRequirement:
+ level: stronglyRecommended
+ scope: publicApps
+ rationale: |
+ Canva strongly recommends using the App UI Kit for public apps to
+ ensure consistent user experience and easier compliance with design
+ guidelines. Without the App UI Kit, meeting the design guidelines
+ can be challenging and may result in slower app review.
+
+ customComponents:
+ allowed: true
+ documentation: https://www.canva.dev/docs/apps/design-guidelines/
+ constraints:
+ - Must use design tokens for consistency
+ - Must support both light and dark themes
+ - Must be accessible (WCAG 2.1 AA minimum)
+ - Must work on both desktop and mobile (recommended)
+ - Should follow Canva's design patterns where applicable
+
+ publishing:
+ privateApps:
+ componentRequirement: recommended
+ customComponentsAllowed: true
+ reviewRequired: false
+ distributionScope: team
+ notes: |
+ Private apps are only available to members of the current team on
+ an Enterprise plan. Team administrators are responsible for review.
+
+ publicApps:
+ componentRequirement: stronglyRecommended
+ customComponentsAllowed: true
+ reviewRequired: true
+ designReviewRequired: true
+ localizationRequired: true
+ submissionLimit: "5 submissions per day"
+ notes: |
+ Public apps are reviewed by Canva's team of engineers, designers,
+ and QA experts. Apps must adhere to design guidelines and functional
+ requirements outlined in the submission checklist.
+
+ designGuidelines:
+ required: true
+ designSystem: Canva Design System
+ designSystemUrl: https://www.figma.com/community/file/1314652421936534778
+ designTokensProvided: true
+ designTokensUrl: https://www.canva.dev/docs/apps/app-ui-kit/design-tokens/
+ themeSupport:
+ - light
+ - dark
+ requirements:
+ - Apps must be tested in both light and dark themes
+ - Mobile compatibility is highly recommended
+ - All interactive elements must be keyboard accessible
+ - Must follow spacing and typography guidelines
+
+ internationalization:
+ required: true
+ scope: publicApps
+ provider: Canva
+ freeTranslation: true
+ freeTranslationConditions: |
+ Canva provides free translation for apps that have successfully
+ completed the app review process. Apps must use the @canva/app-i18n-kit
+ package and react-intl library.
+ supportedDirections:
+ - ltr
+ - rtl
+ implementation:
+ - App UI Kit components support i18n out of the box
+ - Must use react-intl for all user-facing strings
+ - Must use @canva/app-i18n-kit for non-React contexts
+ - Production apps must support multiple languages
+ documentation: https://www.canva.dev/docs/apps/localization/
+
+ security:
+ authentication:
+ signatureVerification: required
+ condition: Apps using Authentication or Fetch capabilities
+ documentation: https://www.canva.dev/docs/apps/submission-checklist/
+
+ sandboxing:
+ iframeSandbox: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+
+renderingEngines:
+ react:
+ type: react
+ name: React 19 Rendering
+ version: "^19.0.0"
+ description: |
+ All Canva apps render as React 19 components. The App UI Kit
+ requires React 19 as a peer dependency.
+ sandboxing:
+ iframeSandbox: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ providers:
+ - AppUiProvider (required for theming and i18n)
+
+extensions:
+ i18n:
+ provider: Canva Translation Service
+ freeForApprovedApps: true
+ package: "@canva/app-i18n-kit"
+ peerDependencies:
+ - react-intl
+ - "@canva/app-ui-kit@^4.0.0"
+ features:
+ - All App UI Kit components support i18n automatically
+ - Bidirectional text support (LTR/RTL)
+ - Translation management through Canva's translation process
+ - No manual translation management required for approved apps
+ implementation:
+ - Wrap app in AppUiProvider
+ - Use react-intl's FormattedMessage for strings
+ - Use initIntl for non-React contexts
+ - Submit app for review to receive free translations
+ supportedLanguages: 100+
+ documentation: https://www.canva.dev/docs/apps/localization/
+
+ compliance:
+ appReviewProcess:
+ enabled: true
+ scope: publicApps
+ reviewers:
+ - Engineers
+ - Designers
+ - QA experts
+ trackingSystem: Jira Service Desk
+ communicationChannel: JSD tickets
+ documentation: https://www.canva.dev/docs/apps/app-review-process/
+
+ submissionChecklist:
+ functionalRequirements:
+ - App works on both desktop and mobile (recommended)
+ - Signature verification implemented (if using auth/fetch)
+ - Tested in light and dark themes
+ - No console errors or warnings
+ designRequirements:
+ - Follows Canva design guidelines
+ - Uses App UI Kit components (strongly recommended)
+ - Consistent with Canva's visual language
+ - Accessible (keyboard navigation, screen readers)
+ documentationRequirements:
+ - Test account credentials (if authentication required)
+ - Platform documentation
+ - Content source documentation (if applicable)
+ url: https://www.canva.dev/docs/apps/submission-checklist/
+
+ designGuidelines:
+ figmaLibrary: https://www.figma.com/community/file/1314652421936534778
+ documentation: https://www.canva.dev/docs/apps/design-guidelines/
+ categories:
+ - Content Publisher apps
+ - Design Publisher apps
+ - Forms and inputs
+ - Mobile considerations
+ reviewSupport: |
+ Canva provides feedback on custom components before and during
+ the review process.
+
+ developerTools:
+ starterKit:
+ repository: https://github.com/canva-sdks/canva-apps-sdk-starter-kit
+ includes:
+ - Boilerplate project structure
+ - App UI Kit
+ - TypeScript configuration
+ - React 19
+ - Webpack configuration
+ - Example apps
+
+ playroom:
+ description: Live playground for App UI Kit components
+ url: https://www.canva.dev/docs/apps/app-ui-kit/quickstart/
+
+ storybook:
+ description: Interactive component documentation
+ availability: Available for exploring App UI Kit components
+
+ devToolkit:
+ features:
+ - Theme toggling (light/dark)
+ - Live reload
+ - Error reporting
+ documentation: https://www.canva.dev/docs/apps/quickstart/
+
+ mcpServer:
+ name: Canva Dev MCP Server
+ description: |
+ Model Context Protocol server for AI coding tools like Cursor
+ or Claude Code to supercharge development workflow.
+ compatibility:
+ - Cursor
+ - Claude Code
+ - Other MCP-compatible tools
+
+jsonFormsIntegration:
+ supported: false
+ notes: "Canva uses its own form components from the App UI Kit"
+
+mcpAppsIntegration:
+ supported: false
+ notes: "Not yet integrated with MCP Apps specification"
diff --git a/specs/fenestra/examples/0.1.0/docusign.fenestra.yaml b/specs/fenestra/examples/0.1.0/docusign.fenestra.yaml
new file mode 100644
index 0000000..412973e
--- /dev/null
+++ b/specs/fenestra/examples/0.1.0/docusign.fenestra.yaml
@@ -0,0 +1,958 @@
+# Fenestra Document: DocuSign Platform
+#
+# DocuSign represents a unique hybrid extension model combining:
+# 1. Embedded SDK - Embed signing experiences directly in your app (iframe-based)
+# 2. Extension Apps - Extend DocuSign workflows with custom logic
+# 3. Agent UI (MCP) - AI agents can interact with DocuSign via Model Context Protocol
+#
+# This makes DocuSign one of the few platforms supporting both traditional embedded
+# experiences AND cutting-edge AI agent interactions.
+
+fenestra: "0.1.0"
+
+info:
+ title: DocuSign Platform UI Ecosystem
+ version: "1.0.0"
+ description: |
+ DocuSign's Intelligent Agreement Management (IAM) platform enables developers
+ to embed eSignature experiences, build extension apps, and integrate with
+ AI agents through the Model Context Protocol.
+
+ Key characteristics:
+ - Embedded Signing: Embed signature workflows directly in your application
+ - Focused View: Modern, minimalist embedded signing experience
+ - Extension Apps: Custom functionality at designated points in agreement workflows
+ - MCP Server: First-class support for AI agents via Model Context Protocol
+ - Enterprise Compliance: SOC 2, GDPR, FedRAMP, eIDAS certified
+ - Legal-grade Security: Built for legally binding electronic signatures
+
+platform:
+ name: DocuSign
+ vendor: DocuSign, Inc.
+ documentation: https://developers.docusign.com/
+ appMarketplace: https://www.docusign.com/app-center
+ changelog: https://www.docusign.com/blog/developers
+
+sdks:
+ docusign-esign:
+ name: DocuSign eSignature Node SDK
+ packageManager: npm
+ package: "docusign-esign"
+ version: "^7.0.0"
+ repository: https://github.com/docusign/docusign-esign-node-client
+ documentation: https://developers.docusign.com/docs/esign-rest-api/sdks/node/
+ description: |
+ Official Node.js SDK for the DocuSign eSignature REST API.
+ Enables requesting signatures, automating forms, and tracking documents
+ directly from your application.
+ installCommand: "npm install docusign-esign"
+ exports:
+ ApiClient:
+ type: utility
+ description: API client for DocuSign eSignature REST API
+ EnvelopesApi:
+ type: utility
+ description: API for creating and managing envelopes (document packages)
+ RecipientViewRequest:
+ type: type
+ description: Request object for generating embedded signing URLs
+ EnvelopeDefinition:
+ type: type
+ description: Defines an envelope with documents and recipients
+ Signer:
+ type: type
+ description: Recipient who needs to sign the document
+ Document:
+ type: type
+ description: Document to be signed
+ SignHere:
+ type: type
+ description: Signature tab placement on document
+ DateSigned:
+ type: type
+ description: Date signed tab placement
+ Text:
+ type: type
+ description: Text input tab for recipients
+
+ docusign-extension-sdk:
+ name: DocuSign Extension App SDK
+ packageManager: npm
+ package: "@docusign/extension-app-sdk"
+ documentation: https://developers.docusign.com/extension-apps/
+ description: |
+ SDK for building DocuSign Extension Apps that extend agreement workflows
+ with custom functionality. Extension apps can validate data, move files
+ across systems, and add custom logic to workflows.
+ exports:
+ ExtensionClient:
+ type: utility
+ description: Client for communicating with DocuSign from extension apps
+ FileInputAction:
+ type: type
+ description: Handle file input in extensions
+ FileOutputAction:
+ type: type
+ description: Output files from extensions
+ ConnectedFieldsApi:
+ type: utility
+ description: Validate data in real-time with Connected Fields
+ ExtensionContext:
+ type: context
+ description: Context provided to extension apps
+
+ docusign-mcp-server:
+ name: DocuSign MCP Server
+ packageManager: npm
+ package: "docusign-mcp-server"
+ repository: https://github.com/docusign/docusign-mcp-server
+ documentation: https://developers.docusign.com/docs/mcp/
+ description: |
+ DocuSign's Model Context Protocol (MCP) server enables AI agents to
+ interact with DocuSign's agreement capabilities using natural language.
+
+ Agents can:
+ - Get summaries of active agreements
+ - Send documents for signature
+ - Check signing status
+ - Manage templates and workflows
+ - Access user information
+ exports:
+ DocuSignMCPServer:
+ type: utility
+ description: MCP server for AI agent integration
+ AgreementTools:
+ type: utility
+ description: Tools for managing agreements via natural language
+ TemplateTools:
+ type: utility
+ description: Tools for working with DocuSign templates
+ AuthTools:
+ type: utility
+ description: Authentication and authorization tools
+
+componentCatalog:
+ categories:
+ embeddedSigning:
+ name: Embedded Signing Components
+ description: Components for embedding signature experiences
+ components:
+ - RecipientView
+ - FocusedView
+ - ClassicView
+
+ extensionUI:
+ name: Extension App UI
+ description: Custom UI components for extension apps
+ components:
+ - ExtensionPanel
+ - ValidationForm
+ - FileSelector
+ - ProgressIndicator
+
+ agentTemplates:
+ name: Agent UI Templates
+ description: Templates for AI agent interactions via MCP
+ components:
+ - SignatureRequest
+ - AgreementStatus
+ - TemplateSelector
+ - RecipientForm
+
+ components:
+ RecipientView:
+ name: Recipient View
+ description: |
+ Embedded signing session that displays the DocuSign signing experience
+ within your application. Generated via the eSignature API using a
+ clientUserId to create a unique, one-time URL for the signing session.
+ category: embeddedSigning
+ sdkBinding:
+ sdk: docusign-esign
+ export: RecipientViewRequest
+ webStandardMapping:
+ htmlElement: iframe
+ ariaRole: document
+ semanticType: embedded_document
+ props:
+ type: object
+ properties:
+ returnUrl:
+ type: string
+ format: uri
+ description: URL to redirect to after signing completes
+ authenticationMethod:
+ type: string
+ default: none
+ description: Authentication method (none for embedded)
+ clientUserId:
+ type: string
+ description: Unique identifier linking envelope recipient to your app user
+ frameAncestors:
+ type: array
+ description: Allowed parent domains for iframe embedding (CSP)
+ items:
+ type: string
+ required:
+ - returnUrl
+ - clientUserId
+ examples:
+ - title: Generate Embedded Signing URL
+ code: |
+ const envelopesApi = new docusign.EnvelopesApi(apiClient);
+ const viewRequest = new docusign.RecipientViewRequest();
+ viewRequest.returnUrl = 'https://myapp.com/signing-complete';
+ viewRequest.authenticationMethod = 'none';
+ viewRequest.clientUserId = 'user123';
+
+ const results = await envelopesApi.createRecipientView(
+ accountId,
+ envelopeId,
+ { recipientViewRequest: viewRequest }
+ );
+ const signingUrl = results.url;
+ language: javascript
+
+ FocusedView:
+ name: Focused View
+ description: |
+ Clean, minimalist embedded signing experience with no DocuSign chrome.
+ Shows only the agreement and navigation, fully branded to your application.
+ Requires additional security configuration with frameAncestors.
+ category: embeddedSigning
+ sdkBinding:
+ sdk: docusign-esign
+ export: RecipientViewRequest
+ webStandardMapping:
+ htmlElement: iframe
+ ariaRole: document
+ semanticType: embedded_document
+ props:
+ type: object
+ properties:
+ returnUrl:
+ type: string
+ format: uri
+ clientUserId:
+ type: string
+ frameAncestors:
+ type: array
+ description: |
+ Required for Focused View. Must include your site's URL and
+ DocuSign's apps domain (apps-d.docusign.com for demo,
+ apps.docusign.com for production)
+ items:
+ type: string
+ minItems: 2
+ required:
+ - returnUrl
+ - clientUserId
+ - frameAncestors
+ constraints:
+ requiresHTTPS: true
+ noIdentityVerification: true
+ noAdvancedSignatures: true
+ examples:
+ - title: Focused View Integration
+ code: |
+ // Server-side: Generate signing URL
+ viewRequest.frameAncestors = [
+ 'https://myapp.com',
+ 'https://apps.docusign.com'
+ ];
+
+ // Client-side: Embed with postMessage
+ const iframe = document.getElementById('docusign-iframe');
+ iframe.src = signingUrl;
+
+ window.addEventListener('message', (event) => {
+ if (event.data.event === 'signing_complete') {
+ // Handle completion
+ }
+ });
+ language: javascript
+
+ ClassicView:
+ name: Classic View
+ description: |
+ Traditional embedded signing experience with full DocuSign UI chrome.
+ Supports all features including identity verification and advanced
+ signature types. Redirects back to your app after completion.
+ category: embeddedSigning
+ sdkBinding:
+ sdk: docusign-esign
+ export: RecipientViewRequest
+ webStandardMapping:
+ htmlElement: iframe
+ ariaRole: document
+ semanticType: embedded_document
+ props:
+ type: object
+ properties:
+ returnUrl:
+ type: string
+ format: uri
+ clientUserId:
+ type: string
+ authenticationMethod:
+ type: string
+ required:
+ - returnUrl
+ - clientUserId
+
+ ExtensionPanel:
+ name: Extension App Panel
+ description: |
+ Custom UI panel displayed in DocuSign at designated extension points
+ during agreement workflows. Communicates with your backend via
+ the Extension App SDK.
+ category: extensionUI
+ sdkBinding:
+ sdk: docusign-extension-sdk
+ export: ExtensionClient
+ webStandardMapping:
+ htmlElement: iframe
+ semanticType: embedded_app
+ props:
+ type: object
+ properties:
+ extensionId:
+ type: string
+ description: Unique identifier for your extension
+ actionType:
+ type: string
+ enum: [fileInput, fileOutput, dataValidation, connectedFields]
+ context:
+ type: object
+ description: DocuSign context (envelope, user, workflow step)
+
+ SignatureRequest:
+ name: Signature Request Template
+ description: |
+ Agent UI template for AI agents to request signatures via MCP.
+ Agent specifies recipients, documents, and signing options using
+ natural language, which maps to DocuSign API calls.
+ category: agentTemplates
+ sdkBinding:
+ sdk: docusign-mcp-server
+ export: AgreementTools
+ webStandardMapping:
+ semanticType: agent_action
+ props:
+ type: object
+ properties:
+ recipients:
+ type: array
+ items:
+ type: object
+ properties:
+ name:
+ type: string
+ email:
+ type: string
+ format: email
+ documents:
+ type: array
+ items:
+ type: object
+ properties:
+ name:
+ type: string
+ url:
+ type: string
+ message:
+ type: string
+ description: Email message to recipients
+
+ AgreementStatus:
+ name: Agreement Status Template
+ description: |
+ Agent UI template for displaying agreement status and history.
+ Agent can query agreement state, view audit trail, and check
+ recipient progress.
+ category: agentTemplates
+ sdkBinding:
+ sdk: docusign-mcp-server
+ export: AgreementTools
+ webStandardMapping:
+ semanticType: agent_display
+ props:
+ type: object
+ properties:
+ envelopeId:
+ type: string
+ includeAuditTrail:
+ type: boolean
+ includeRecipientStatus:
+ type: boolean
+
+extensionPoints:
+ - id: embedded-signing
+ name: Embedded Signing
+ type: embedded
+ extensionType: embeddedSdk
+ description: |
+ Embed the DocuSign signing experience directly within your application.
+ Users can review and sign documents without leaving your app.
+
+ Supports two rendering modes:
+ - Focused View: Minimal UI, fully branded experience
+ - Classic View: Full DocuSign UI with all features
+ supportedComponents:
+ - RecipientView
+ - FocusedView
+ - ClassicView
+ extensionTypeConfig:
+ rendering: iframe
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ - allow-same-origin
+ - allow-popups
+ communication:
+ method: postMessage
+ events:
+ - signing_complete
+ - sessionEnd
+ - ttl_expired
+ - cancel
+ - decline
+ - exception
+ security:
+ requiresClientUserId: true
+ oneTimeUrl: true
+ cspRequired: true
+ httpsRequired: true
+ constraints:
+ maxSessionDuration: 300
+ sessionTimeoutMinutes: 5
+ requiresHTTPS: true
+ context:
+ provides:
+ - envelopeId
+ - recipientId
+ - signingComplete
+ - declineReason
+ actions:
+ - createRecipientView
+ - handleSigningComplete
+ - refreshSession
+ documentation: https://developers.docusign.com/docs/esign-rest-api/esign101/concepts/embedding/
+
+ - id: extension-app
+ name: Extension Apps
+ type: workflow
+ extensionType: codedComponents
+ description: |
+ Extend DocuSign agreement workflows with custom functionality activated
+ at specific points in the process. Extension apps can:
+ - Validate data in real-time (Connected Fields)
+ - Move files between systems (File I/O)
+ - Add custom business logic to workflows
+ - Integrate with external APIs
+ supportedComponents:
+ - ExtensionPanel
+ - ValidationForm
+ - FileSelector
+ - ProgressIndicator
+ extensionTypeConfig:
+ runtime:
+ type: serverSide
+ hosting: developer
+ communication:
+ method: https
+ protocol: rest
+ triggers:
+ - agreementCreated
+ - beforeSending
+ - afterSigning
+ - statusChanged
+ - fieldValidation
+ constraints:
+ privateAppsSupported: true
+ publicAppsRequireReview: true
+ context:
+ provides:
+ - envelopeId
+ - workflowStepId
+ - accountId
+ - userId
+ - documentData
+ actions:
+ - validateField
+ - fetchFileInput
+ - sendFileOutput
+ - updateWorkflowData
+ documentation: https://developers.docusign.com/extension-apps/
+
+ - id: mcp-agent-ui
+ name: AI Agent Integration (MCP)
+ type: agent
+ extensionType: agentUI
+ description: |
+ Model Context Protocol integration enabling AI agents to interact with
+ DocuSign's agreement management capabilities using natural language.
+
+ Agents can:
+ - Send documents for signature
+ - Check agreement status
+ - Manage templates
+ - Query recipient progress
+ - Access audit trails
+
+ This positions DocuSign at the forefront of AI-native document workflows.
+ extensionTypeConfig:
+ protocol: mcp
+ version: "1.0.0"
+ transport: stdio
+ templates:
+ supported:
+ - signatureRequest
+ - agreementStatus
+ - templateSelector
+ - recipientForm
+ definitions:
+ signatureRequest:
+ name: Signature Request
+ description: Request signatures on documents
+ inputSchema:
+ type: object
+ properties:
+ recipients:
+ type: array
+ documents:
+ type: array
+ emailSubject:
+ type: string
+ required:
+ - recipients
+ - documents
+ outputSchema:
+ type: object
+ properties:
+ envelopeId:
+ type: string
+ status:
+ type: string
+ signingUrl:
+ type: string
+
+ agreementStatus:
+ name: Agreement Status
+ description: Get status of agreement
+ inputSchema:
+ type: object
+ properties:
+ envelopeId:
+ type: string
+ required:
+ - envelopeId
+ outputSchema:
+ type: object
+ properties:
+ status:
+ type: string
+ recipients:
+ type: array
+ auditTrail:
+ type: object
+
+ tools:
+ - name: sendEnvelope
+ description: Send documents for signature
+ - name: getEnvelopeStatus
+ description: Get status of envelope
+ - name: listTemplates
+ description: List available templates
+ - name: createEnvelopeFromTemplate
+ description: Create envelope from template
+ - name: getAccountInfo
+ description: Get account information
+
+ agentCapabilities:
+ invokeTemplates: true
+ executeTools: true
+ receiveContext: true
+ chainOperations: true
+
+ context:
+ provides:
+ - accountId
+ - accessToken
+ - baseUrl
+ - userInfo
+ actions:
+ - sendDocument
+ - checkStatus
+ - useTemplate
+ - getAuditTrail
+
+ documentation: https://developers.docusign.com/docs/mcp/
+
+policies:
+ componentRequirement:
+ level: required
+ scope: embeddedSigning
+ rationale: |
+ Embedded signing experiences must use DocuSign's provided recipient
+ view API and iframe rendering. This ensures security, legal compliance,
+ and audit trail integrity for legally binding signatures.
+
+ customComponents:
+ allowed: true
+ constraints:
+ - scope: extensionApps
+ - sandboxOnly: true
+ - reviewRequired: true
+ registrationRequired: true
+ approvalRequired: true
+ documentation: https://developers.docusign.com/extension-apps/build-an-extension-app/
+ rationale: |
+ Extension Apps can include custom UI rendered in sandboxed iframes.
+ Public extension apps undergo security review. Private apps have
+ more flexibility but still must follow security guidelines.
+
+ publishing:
+ privateApps:
+ name: Private Extensions
+ componentRequirement: optional
+ customComponentsAllowed: true
+ reviewRequired: false
+ notes: |
+ Private extension apps for internal use have flexibility in
+ UI implementation. Still must follow security best practices.
+
+ publicApps:
+ name: DocuSign App Center
+ componentRequirement: required
+ customComponentsAllowed: true
+ reviewRequired: true
+ securityReviewRequired: true
+ certificationRequired: false
+ notes: |
+ Public extension apps listed in App Center undergo:
+ - Security review
+ - Functionality testing
+ - UX assessment
+ - Data handling audit
+ reviewTimeline: "2-4 weeks typical"
+
+ designGuidelines:
+ required: true
+ designSystem: "DocuSign Design System"
+ designSystemUrl: https://developers.docusign.com/design/
+ guidelines:
+ - Maintain DocuSign brand consistency in embedded experiences
+ - Follow accessibility guidelines (WCAG 2.1 AA)
+ - Provide clear user feedback during signing
+ - Handle errors gracefully with user-friendly messages
+ - Support responsive layouts for mobile signing
+
+ security:
+ sandbox: true
+ sandboxDescription: |
+ All embedded signing and extension app UI runs in sandboxed iframes
+ with strict CSP policies. Communication uses postMessage or HTTPS.
+ requirements:
+ - HTTPS required for all embedded signing
+ - CSP frameAncestors must be explicitly declared
+ - One-time signing URLs with TTL expiration
+ - Client user ID required to prevent URL reuse
+ - Request signature verification for extension apps
+ - OAuth 2.0 with JWT for API authentication
+ certifications:
+ - SOC 2 Type 2
+ - ISO 27001
+ - GDPR compliant
+ - FedRAMP authorized
+ - eIDAS qualified (EU)
+ - PCI DSS compliant (payment tabs)
+ auditTrail:
+ enabled: true
+ tamperEvident: true
+ description: |
+ Every signing event is logged with timestamps and IP addresses.
+ Completed documents are sealed with tamper-evident technology.
+
+renderingEngines:
+ docusign-native:
+ type: native
+ name: DocuSign Native Rendering
+ description: |
+ DocuSign's signing experience is rendered natively by DocuSign's
+ platform and embedded in your application via iframe. This ensures
+ legal compliance, consistent UX, and security.
+ sandboxing:
+ iframeSandbox: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ - allow-same-origin
+ - allow-popups
+ cspPolicy: "frame-ancestors 'self' https://*.docusign.com https://*.docusign.net"
+ platforms:
+ - Web (Desktop)
+ - Web (Mobile)
+ - iOS (WebView)
+ - Android (WebView)
+
+ extension-iframe:
+ type: custom
+ name: Extension App Iframe
+ description: |
+ Extension apps render custom UI in sandboxed iframes within
+ DocuSign workflows. Apps communicate with DocuSign via Extension SDK.
+ sandboxing:
+ iframeSandbox: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ communication: postMessage
+
+ mcp-agent:
+ type: agent
+ name: MCP Agent Renderer
+ description: |
+ AI agents interact with DocuSign through Model Context Protocol.
+ No traditional UI rendering - agents use natural language to invoke
+ tools and receive structured responses.
+ protocol: mcp
+ transport: stdio
+ schemaSupport:
+ inputSchema: jsonSchema
+ outputSchema: jsonSchema
+
+architecture:
+ executionModel: hybrid
+ description: |
+ DocuSign supports multiple execution models:
+
+ 1. Embedded Signing: Client-side iframe rendering of DocuSign UI
+ 2. Extension Apps: Server-side execution with iframe UI rendering
+ 3. MCP Agents: Server-to-server protocol communication
+
+ This hybrid approach enables everything from traditional embedded UX
+ to cutting-edge AI agent workflows.
+
+ communication:
+ embeddedSigning:
+ protocol: postMessage
+ description: |
+ Signing iframe communicates with parent application via postMessage.
+ Events include signing_complete, sessionEnd, ttl_expired, etc.
+
+ extensionApps:
+ protocol: https
+ description: |
+ Extension apps communicate with DocuSign via HTTPS webhooks and
+ REST API calls. Extension SDK handles authentication and routing.
+
+ mcpAgents:
+ protocol: mcp
+ transport: stdio
+ description: |
+ AI agents communicate with DocuSign MCP server via standard I/O
+ using JSON-RPC 2.0 messages over stdio transport.
+
+jsonFormsIntegration:
+ supported: false
+ notes: |
+ DocuSign uses proprietary tab definitions for form fields on documents.
+ Not compatible with JSON Forms, but provides similar schema-driven
+ field placement through the eSignature API.
+
+mcpAppsIntegration:
+ supported: true
+ implementation: docusign-mcp-server
+ notes: |
+ DocuSign is one of the first enterprise platforms to provide native
+ MCP server support, enabling AI agents to manage agreements through
+ natural language interactions.
+ version: "1.0.0"
+ transport: stdio
+ capabilities:
+ - tools
+ - resources
+ - prompts
+
+extensions:
+ agentInteraction:
+ enabled: true
+ protocol: mcp
+ serverPackage: docusign-mcp-server
+ description: |
+ DocuSign's MCP server enables AI agents to:
+ - Send documents for signature using natural language
+ - Check agreement status and recipient progress
+ - Use templates to streamline document creation
+ - Access audit trails and signing history
+ - Manage account settings and users
+
+ useCases:
+ - Automated contract generation and signing
+ - Agreement status monitoring and reporting
+ - Template-based document workflows
+ - Integration with AI assistants (Claude, ChatGPT, etc.)
+ - Conversational agreement management
+
+ chatGPTIntegration:
+ available: true
+ url: https://chatgpt.com/
+ description: |
+ DocuSign IAM will be available in ChatGPT, enabling users and
+ AI agents to create, sign, and manage contracts through natural
+ conversation.
+
+ compliance:
+ enabled: true
+ legalCompliance:
+ eSignatureAct: true
+ description: |
+ DocuSign complies with the U.S. ESIGN Act and UETA, making
+ signatures legally binding in the United States.
+ jurisdictions:
+ - United States (ESIGN, UETA)
+ - European Union (eIDAS)
+ - United Kingdom (eIDAS UK)
+ - Canada (PIPEDA)
+ - Australia (Electronic Transactions Act)
+ - Global (180+ countries)
+
+ certifications:
+ - name: SOC 2 Type 2
+ description: Annual audits of security, availability, and confidentiality
+ scope: all
+
+ - name: ISO 27001:2013
+ description: Information security management system certification
+ scope: all
+
+ - name: GDPR
+ description: EU General Data Protection Regulation compliance
+ scope: eu
+ features:
+ - Binding Corporate Rules (BCRs)
+ - Data processing agreements
+ - Right to erasure
+ - Data portability
+
+ - name: FedRAMP
+ description: Federal Risk and Authorization Management Program
+ scope: government
+ level: Agency Authorization
+
+ - name: eIDAS
+ description: Electronic Identification and Trust Services (EU)
+ scope: eu
+ capabilities:
+ - Qualified Electronic Signatures (QES)
+ - Advanced Electronic Signatures (AES)
+ - Qualified Time Stamps
+ - Trust Service Provider status
+
+ - name: PCI DSS v4.0
+ description: Payment Card Industry Data Security Standard
+ scope: paymentTabs
+
+ dataResidency:
+ available: true
+ regions:
+ - United States
+ - European Union
+ - Canada
+ - Australia
+ - United Kingdom
+ - Japan
+ description: |
+ DocuSign offers data residency options for customers with
+ regulatory requirements to store data in specific geographic regions.
+
+ auditTrail:
+ type: tamperEvident
+ description: |
+ Every action is logged with cryptographic sealing:
+ - Document access (views, prints)
+ - Signature events with timestamps
+ - IP addresses and authentication methods
+ - Changes to envelope status
+ - Certificate of completion with tamper-evident seal
+
+ webhooks:
+ enabled: true
+ description: |
+ DocuSign Connect webhooks notify your application of envelope events
+ in real-time. Useful for tracking signing progress and triggering
+ downstream workflows.
+ events:
+ - envelope_sent
+ - envelope_delivered
+ - envelope_completed
+ - envelope_declined
+ - envelope_voided
+ - recipient_sent
+ - recipient_delivered
+ - recipient_completed
+ - recipient_declined
+ delivery:
+ protocol: https
+ method: POST
+ retryPolicy: exponential_backoff
+ signature: HMAC-SHA256
+ configuration:
+ url: https://developers.docusign.com/platform/webhooks/connect/
+ setup: "Configure in DocuSign Admin Console or via API"
+
+ analytics:
+ enabled: true
+ description: |
+ DocuSign provides analytics on agreement activity, completion rates,
+ and user engagement through the Admin Console.
+ metrics:
+ - Envelopes sent/completed
+ - Average time to complete
+ - Recipient engagement
+ - Template usage
+ - API usage statistics
+ dashboard: "DocuSign Admin Console - Reports"
+
+notes: |
+ DocuSign represents a pioneering approach to document agreement platforms
+ by supporting BOTH traditional embedded SDK experiences AND modern AI agent
+ interactions through the Model Context Protocol.
+
+ Key differentiators:
+ - Legal-grade eSignature compliance (180+ countries)
+ - Enterprise security (SOC 2, ISO 27001, FedRAMP, eIDAS)
+ - Embedded Signing: Seamless signature workflows in your app
+ - Focused View: Modern, branded signing experience
+ - Extension Apps: Custom workflow logic and integrations
+ - MCP Server: First-class AI agent support
+ - Global reach: Legally binding signatures worldwide
+
+ DocuSign's MCP integration positions it as a leader in AI-native document
+ workflows, enabling natural language interactions for agreement management
+ while maintaining the highest standards of security and legal compliance.
+
+metadata:
+ fenestra:
+ createdAt: "2025-12-30"
+ author: "Fenestra Specification Team"
+ category: "Document Management & eSignature"
+ tags:
+ - esignature
+ - document-management
+ - embedded-signing
+ - mcp
+ - ai-agents
+ - compliance
+ - legal-tech
+ - enterprise
+ relatedPlatforms:
+ - Adobe Sign
+ - HelloSign
+ - SignNow
+ - PandaDoc
+ extensionTypes:
+ - embeddedSdk
+ - agentUI
+ - codedComponents
diff --git a/specs/fenestra/examples/0.1.0/figma.fenestra.yaml b/specs/fenestra/examples/0.1.0/figma.fenestra.yaml
new file mode 100644
index 0000000..2409b6d
--- /dev/null
+++ b/specs/fenestra/examples/0.1.0/figma.fenestra.yaml
@@ -0,0 +1,727 @@
+# Fenestra Document: Figma Plugin Platform
+#
+# Figma represents an iframe-based execution model with dual-context architecture.
+# Plugins run in two separate contexts: main thread (Figma API access) and UI thread (sandboxed iframe).
+
+fenestra: "0.1.0"
+
+info:
+ title: Figma Plugin Platform UI Ecosystem
+ version: "1.0.0"
+ description: |
+ Figma's Plugin Platform enables developers to extend Figma and FigJam
+ with custom functionality through a dual-context architecture.
+
+ Key characteristics:
+ - Two execution contexts: Main thread (Figma API) + UI thread (iframe)
+ - Communication via postMessage between contexts
+ - Sandboxed iframe for all UI rendering
+ - Component libraries are OPTIONAL (developers can use figma-plugin-ds or custom HTML/CSS)
+ - Widget API for on-canvas interactive elements
+ - Separate FigJam plugin capabilities
+
+platform:
+ name: Figma
+ vendor: Figma, Inc.
+ documentation: https://www.figma.com/plugin-docs/
+ appMarketplace: https://www.figma.com/community/plugins
+
+sdks:
+ figma-plugin-api:
+ name: Figma Plugin API
+ packageManager: npm
+ package: "@figma/plugin-typings"
+ documentation: https://www.figma.com/plugin-docs/api/api-overview/
+ description: |
+ TypeScript type definitions for the Figma Plugin API.
+ Provides types for the global 'figma' object available in the main thread.
+ exports:
+ figma:
+ type: utility
+ description: Global figma object for document manipulation and API access
+ PluginAPI:
+ type: type
+ description: TypeScript interface for the Figma Plugin API
+ SceneNode:
+ type: type
+ description: Base type for all nodes in the Figma document
+ FrameNode:
+ type: type
+ description: Frame node type
+ TextNode:
+ type: type
+ description: Text node type
+ RectangleNode:
+ type: type
+ description: Rectangle node type
+
+ figma-plugin-ds:
+ name: Figma Plugin DS (Community)
+ packageManager: npm
+ package: "figma-plugin-ds"
+ repository: https://github.com/thomas-lowry/figma-plugin-ds
+ documentation: https://github.com/thomas-lowry/figma-plugin-ds
+ description: |
+ Community-created design system that provides CSS styles matching
+ Figma's UI. Not officially maintained by Figma but widely used.
+ Works with plain HTML similar to Mirotone for Miro.
+ exports:
+ button:
+ type: component
+ description: ".button CSS class for buttons"
+ input:
+ type: component
+ description: ".input CSS class for text inputs"
+ select:
+ type: component
+ description: ".select-menu CSS class for dropdowns"
+ checkbox:
+ type: component
+ description: ".checkbox CSS class for checkboxes"
+ radio:
+ type: component
+ description: ".radio CSS class for radio buttons"
+ switch:
+ type: component
+ description: ".switch CSS class for toggle switches"
+ textarea:
+ type: component
+ description: ".textarea CSS class for text areas"
+ icon:
+ type: component
+ description: ".icon CSS class for icons"
+ disclosure:
+ type: component
+ description: ".disclosure CSS class for collapsible sections"
+ label:
+ type: component
+ description: ".label CSS class for form labels"
+ section:
+ type: component
+ description: ".section CSS class for content sections"
+
+ figma-widget-api:
+ name: Figma Widget API
+ packageManager: npm
+ package: "@figma/plugin-typings"
+ documentation: https://www.figma.com/widget-docs/
+ description: |
+ API for creating interactive on-canvas widgets in Figma.
+ Widgets use a React-like declarative syntax and run directly on the canvas.
+ exports:
+ widget:
+ type: utility
+ description: Global widget namespace for creating on-canvas widgets
+ AutoLayout:
+ type: component
+ description: Auto layout container for widgets
+ Frame:
+ type: component
+ description: Frame container for widgets
+ Text:
+ type: component
+ description: Text display for widgets
+ Rectangle:
+ type: component
+ description: Rectangle shape for widgets
+ SVG:
+ type: component
+ description: SVG display for widgets
+ Input:
+ type: component
+ description: Text input for widgets
+ useSyncedState:
+ type: hook
+ description: Hook for synced state across widget instances
+
+componentCatalog:
+ categories:
+ action:
+ name: Actions
+ description: Interactive elements
+ components: [button, iconButton]
+
+ input:
+ name: Inputs
+ description: Form controls
+ components: [input, textarea, select, checkbox, radio, switch]
+
+ layout:
+ name: Layout
+ description: Layout components
+ components: [section, disclosure, divider]
+
+ display:
+ name: Display
+ description: Display components
+ components: [label, icon]
+
+ widget:
+ name: Widgets
+ description: On-canvas widget components
+ components: [widgetAutoLayout, widgetText, widgetInput, widgetFrame]
+
+ components:
+ button:
+ name: Button
+ description: Figma-styled button component
+ category: action
+ sdkBinding:
+ sdk: figma-plugin-ds
+ export: button
+ webStandardMapping:
+ htmlElement: button
+ ariaRole: button
+ semanticType: action
+ props:
+ class:
+ type: string
+ description: "CSS classes: .button, .button--primary, .button--secondary, .button--tertiary"
+ variants:
+ - primary
+ - secondary
+ - tertiary
+ - destructive
+ examples:
+ - title: Primary Button
+ code: |
+
+ language: html
+ - title: Icon Button
+ code: |
+
+ language: html
+
+ input:
+ name: Input
+ description: Text input field styled to match Figma
+ category: input
+ sdkBinding:
+ sdk: figma-plugin-ds
+ export: input
+ webStandardMapping:
+ htmlElement: input
+ ariaRole: textbox
+ semanticType: input
+ props:
+ class:
+ type: string
+ description: "CSS class: .input"
+ placeholder:
+ type: string
+ examples:
+ - title: Text Input
+ code: |
+
+ language: html
+
+ select:
+ name: Select Menu
+ description: Dropdown menu styled to match Figma
+ category: input
+ sdkBinding:
+ sdk: figma-plugin-ds
+ export: select
+ webStandardMapping:
+ htmlElement: select
+ ariaRole: listbox
+ semanticType: input
+ examples:
+ - title: Select Menu
+ code: |
+
+ language: html
+
+ checkbox:
+ name: Checkbox
+ description: Checkbox styled to match Figma
+ category: input
+ sdkBinding:
+ sdk: figma-plugin-ds
+ export: checkbox
+ webStandardMapping:
+ htmlElement: input[type="checkbox"]
+ ariaRole: checkbox
+ semanticType: input
+ examples:
+ - title: Checkbox
+ code: |
+
+ language: html
+
+ switch:
+ name: Switch
+ description: Toggle switch styled to match Figma
+ category: input
+ sdkBinding:
+ sdk: figma-plugin-ds
+ export: switch
+ webStandardMapping:
+ htmlElement: input[type="checkbox"]
+ ariaRole: switch
+ semanticType: input
+ examples:
+ - title: Switch
+ code: |
+
+ language: html
+
+ section:
+ name: Section
+ description: Content section container
+ category: layout
+ sdkBinding:
+ sdk: figma-plugin-ds
+ export: section
+ webStandardMapping:
+ htmlElement: section
+ ariaRole: region
+ semanticType: container
+ examples:
+ - title: Section
+ code: |
+
+
Section Title
+
+ Content goes here
+
+
+ language: html
+
+ disclosure:
+ name: Disclosure
+ description: Collapsible section with expand/collapse
+ category: layout
+ sdkBinding:
+ sdk: figma-plugin-ds
+ export: disclosure
+ webStandardMapping:
+ htmlElement: details
+ ariaRole: group
+ semanticType: container
+ examples:
+ - title: Disclosure
+ code: |
+
+ language: html
+
+ widgetAutoLayout:
+ name: Widget AutoLayout
+ description: Auto layout container for on-canvas widgets
+ category: widget
+ sdkBinding:
+ sdk: figma-widget-api
+ export: AutoLayout
+ webStandardMapping:
+ htmlElement: div
+ semanticType: layout
+ examples:
+ - title: Widget AutoLayout
+ code: |
+ const { widget } = figma;
+ const { AutoLayout, Text } = widget;
+
+ function Widget() {
+ return (
+
+ Hello World
+
+ );
+ }
+ language: jsx
+
+ widgetText:
+ name: Widget Text
+ description: Text display for on-canvas widgets
+ category: widget
+ sdkBinding:
+ sdk: figma-widget-api
+ export: Text
+ webStandardMapping:
+ htmlElement: span
+ semanticType: display
+ examples:
+ - title: Widget Text
+ code: |
+
+ Widget text content
+
+ language: jsx
+
+ widgetInput:
+ name: Widget Input
+ description: Text input field for on-canvas widgets
+ category: widget
+ sdkBinding:
+ sdk: figma-widget-api
+ export: Input
+ webStandardMapping:
+ htmlElement: input
+ semanticType: input
+ examples:
+ - title: Widget Input
+ code: |
+ const [value, setValue] = useSyncedState('text', '');
+ return (
+ setValue(e.characters)}
+ placeholder="Enter text"
+ />
+ );
+ language: jsx
+
+policies:
+ componentRequirement:
+ level: optional
+ scope: all
+ rationale: |
+ Figma provides no official component library. The community-maintained
+ figma-plugin-ds is popular but entirely optional. Developers have
+ complete freedom to build UIs with any HTML/CSS/JS approach.
+
+ customComponents:
+ allowed: true
+ constraints:
+ - sandboxOnly
+ registrationRequired: false
+ approvalRequired: false
+ documentation: https://www.figma.com/plugin-docs/creating-ui/
+
+ publishing:
+ privateApps:
+ componentRequirement: optional
+ customComponentsAllowed: true
+ reviewRequired: false
+ notes: "Private plugins have complete freedom"
+
+ publicApps:
+ componentRequirement: optional
+ customComponentsAllowed: true
+ reviewRequired: true
+ notes: "Community plugins undergo review for security and quality"
+
+ marketplaceApps:
+ componentRequirement: optional
+ customComponentsAllowed: true
+ certificationRequired: false
+ notes: "All community plugins follow same review process"
+
+ designGuidelines:
+ required: false
+ designSystem: "figma-plugin-ds (community)"
+ designSystemUrl: https://github.com/thomas-lowry/figma-plugin-ds
+ designTokensProvided: false
+
+ security:
+ sandbox: true
+ sandboxDescription: |
+ All plugin UI runs in a sandboxed iframe. The main plugin code
+ runs in a separate JavaScript context with access to the Figma API
+ but no DOM access. Communication between contexts uses postMessage.
+ cspPolicy: "default-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src https:"
+
+extensionPoints:
+ - id: plugin-ui
+ name: Plugin UI
+ type: modal
+ extensionType: iframe
+ description: |
+ Sandboxed iframe UI that can be shown as a modal or panel.
+ Communicates with main plugin code via postMessage.
+ supportedComponents:
+ - all
+ constraints:
+ resizable: true
+ responsive: true
+ context:
+ provides:
+ - selection
+ - currentPage
+ - document
+ - user
+ actions:
+ - createNode
+ - modifyNode
+ - deleteNode
+ - showUI
+ - closePlugin
+ extensionTypeConfig:
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ communication:
+ globalObject: "parent"
+ initialization:
+ method: "postMessage to parent"
+ async: true
+ asyncPattern: promises
+ capabilities:
+ context: true
+ uiActions: true
+ dataActions: true
+ events: true
+
+ - id: widget-canvas
+ name: Canvas Widget (Figma)
+ type: canvas
+ extensionType: codedComponents
+ description: |
+ Interactive on-canvas widget that lives in the Figma document.
+ Uses a React-like declarative API with limited component set.
+ Available in Figma files (not FigJam).
+ supportedComponents:
+ - widgetAutoLayout
+ - widgetText
+ - widgetInput
+ - widgetFrame
+ constraints:
+ responsive: true
+ context:
+ provides:
+ - widgetNode
+ - syncedState
+ - document
+ actions:
+ - updateWidget
+ - openUI
+ extensionTypeConfig:
+ sdk: figma-widget-api
+ framework: react
+ runtime:
+ type: directExecution
+ bundling: platformBuild
+
+ - id: figjam-widget
+ name: FigJam Widget
+ type: canvas
+ extensionType: codedComponents
+ description: |
+ Interactive widget for FigJam collaborative whiteboard.
+ Similar to Figma widgets but with FigJam-specific features.
+ Can include stickers, voting, and collaboration features.
+ supportedComponents:
+ - widgetAutoLayout
+ - widgetText
+ - widgetInput
+ - widgetFrame
+ constraints:
+ responsive: true
+ context:
+ provides:
+ - widgetNode
+ - syncedState
+ - figjamDocument
+ actions:
+ - updateWidget
+ - openUI
+ - createSticky
+ extensionTypeConfig:
+ sdk: figma-widget-api
+ framework: react
+ runtime:
+ type: directExecution
+ bundling: platformBuild
+
+ - id: plugin-menu
+ name: Plugin Menu Command
+ type: contextMenu
+ extensionType: codedComponents
+ description: |
+ Command in the Figma plugins menu that executes code without showing UI.
+ Can optionally open UI after execution.
+ supportedComponents: []
+ context:
+ provides:
+ - selection
+ - currentPage
+ - document
+ actions:
+ - createNode
+ - modifyNode
+ - showUI
+
+renderingEngines:
+ iframe-html:
+ type: custom
+ name: HTML + CSS in Iframe
+ description: |
+ Plugin UI is plain HTML/CSS/JavaScript rendered in a sandboxed iframe.
+ Developers can use figma-plugin-ds CSS library or custom styling.
+ sandboxing:
+ iframeSandbox: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ cspPolicy: "default-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
+
+ widget-declarative:
+ type: custom
+ name: Widget Declarative API
+ description: |
+ On-canvas widgets use a React-like declarative syntax with a limited
+ set of built-in components (AutoLayout, Text, Input, etc.)
+ sandboxing:
+ iframeSandbox: false
+
+architecture:
+ executionModel: dual-context
+ description: |
+ Figma plugins use a dual-context architecture:
+
+ 1. Main Thread: Runs plugin code with access to Figma API (figma.*)
+ - No DOM access
+ - Can read/write document nodes
+ - Can trigger UI display
+
+ 2. UI Thread: Sandboxed iframe with HTML/CSS/JS
+ - Full DOM access for rendering UI
+ - No direct Figma API access
+ - Communicates with main thread via postMessage
+
+ This separation ensures security while allowing rich custom UIs.
+
+ communication:
+ protocol: postMessage
+ description: |
+ Main thread and UI thread communicate via window.postMessage API.
+
+ Main -> UI: figma.ui.postMessage(data)
+ UI -> Main: parent.postMessage({ pluginMessage: data }, '*')
+
+ Main thread listens: figma.ui.onmessage = (msg) => { ... }
+ UI thread listens: window.onmessage = (event) => { ... }
+
+jsonFormsIntegration:
+ supported: true
+ rendererSet: custom
+ customRenderersAllowed: true
+ notes: |
+ Developers can integrate JSON Forms with custom renderers using
+ figma-plugin-ds or their own components in the UI iframe.
+
+mcpAppsIntegration:
+ supported: false
+ notes: |
+ Not currently integrated with MCP Apps specification, but the iframe
+ architecture could potentially support MCP Apps UI resources in the future.
+
+extensions:
+ compliance:
+ communityGuidelines:
+ url: https://www.figma.com/community/plugin-guidelines/
+ description: |
+ Figma Community Guidelines govern what plugins can be published.
+ Key requirements:
+ - No malicious code or data harvesting
+ - Must respect user privacy
+ - Clear description of functionality
+ - Appropriate content only
+ - No trademark/copyright violations
+
+ reviewProcess:
+ required: true
+ scope: public
+ description: |
+ All community plugins undergo review before publication:
+ 1. Automated security checks
+ 2. Manual review of code and functionality
+ 3. Testing for performance and stability
+ 4. Verification of description accuracy
+ timeline: "1-2 weeks typical review time"
+
+ securityRequirements:
+ - name: Sandboxing
+ description: All UI must run in sandboxed iframe
+ required: true
+ - name: API Access
+ description: Only access Figma API from main thread
+ required: true
+ - name: Network Requests
+ description: Declare all network requests in manifest
+ required: true
+ - name: Data Privacy
+ description: No unauthorized data collection or transmission
+ required: true
+
+ manifest:
+ file: manifest.json
+ description: |
+ Every plugin requires a manifest.json file defining:
+ - Plugin metadata (name, id, version)
+ - Main code file path
+ - UI file path (if using UI)
+ - Permissions and capabilities
+ - Menu commands
+ - Network access requirements
+ schema:
+ name:
+ type: string
+ required: true
+ id:
+ type: string
+ required: true
+ description: Unique plugin ID assigned by Figma
+ api:
+ type: string
+ required: true
+ description: Figma API version (e.g., "1.0.0")
+ main:
+ type: string
+ required: true
+ description: Path to main plugin code file
+ ui:
+ type: string
+ required: false
+ description: Path to UI HTML file
+ capabilities:
+ type: array
+ required: false
+ description: Special capabilities (e.g., "codegen", "inspect")
+ networkAccess:
+ type: object
+ required: false
+ description: Allowed network domains
+
+ developmentTools:
+ - name: Figma Plugin API Typings
+ description: TypeScript definitions for Figma Plugin API
+ package: "@figma/plugin-typings"
+
+ - name: Create Figma Plugin
+ description: CLI tool for scaffolding new plugins
+ package: "create-figma-plugin"
+ command: "npm init figma-plugin"
+ url: https://github.com/yuanqing/create-figma-plugin
+
+ - name: Figma Plugin DS
+ description: Community design system matching Figma's UI
+ package: "figma-plugin-ds"
+ url: https://github.com/thomas-lowry/figma-plugin-ds
+
+ - name: Hot Reload
+ description: Built-in hot reload during development
+ builtin: true
+ description: "Figma supports hot reload in development mode"
diff --git a/specs/fenestra/examples/0.1.0/hubspot.fenestra.yaml b/specs/fenestra/examples/0.1.0/hubspot.fenestra.yaml
new file mode 100644
index 0000000..6177bcc
--- /dev/null
+++ b/specs/fenestra/examples/0.1.0/hubspot.fenestra.yaml
@@ -0,0 +1,354 @@
+# Fenestra Document: HubSpot UI Extensions
+#
+# HubSpot represents the "required components" end of the spectrum.
+# Developers MUST use the provided SDK components exclusively.
+
+fenestra: "0.1.0"
+
+info:
+ title: HubSpot UI Extensions Ecosystem
+ version: "1.0.0"
+ description: |
+ HubSpot's UI Extensions SDK provides React-based components for building
+ CRM cards, custom tabs, and sidebar extensions within HubSpot.
+
+ Key characteristic: Component usage is REQUIRED - you can only use
+ components provided through the UI Extensions SDK.
+
+platform:
+ name: HubSpot
+ vendor: HubSpot, Inc.
+ documentation: https://developers.hubspot.com/docs/platform/ui-extensions-overview
+ appMarketplace: https://ecosystem.hubspot.com/marketplace/apps
+
+sdks:
+ hubspot-ui-extensions:
+ name: HubSpot UI Extensions SDK
+ packageManager: npm
+ package: "@hubspot/ui-extensions"
+ version: "^0.11.2"
+ repository: https://github.com/HubSpot/ui-extensions-examples
+ documentation: https://developers.hubspot.com/docs/platform/ui-extensions-sdk
+ exports:
+ # Layout Components
+ Flex:
+ type: component
+ description: Flexbox layout container
+ Box:
+ type: component
+ description: Generic box container
+ Divider:
+ type: component
+ description: Visual separator
+ Tile:
+ type: component
+ description: Card-like container
+
+ # Action Components
+ Button:
+ type: component
+ description: Primary action button
+ ButtonRow:
+ type: component
+ description: Row of action buttons
+ Link:
+ type: component
+ description: Navigation link
+
+ # Input Components
+ Input:
+ type: component
+ description: Text input field
+ TextArea:
+ type: component
+ description: Multi-line text input
+ Select:
+ type: component
+ description: Dropdown selection
+ DateInput:
+ type: component
+ description: Date picker
+ NumberInput:
+ type: component
+ description: Numeric input
+ Toggle:
+ type: component
+ description: Boolean toggle switch
+ Checkbox:
+ type: component
+ description: Checkbox input
+
+ # Display Components
+ Text:
+ type: component
+ description: Text display
+ Heading:
+ type: component
+ description: Section heading
+ Alert:
+ type: component
+ description: Alert/notification message
+ Badge:
+ type: component
+ description: Status badge
+ Tag:
+ type: component
+ description: Label tag
+ Image:
+ type: component
+ description: Image display
+ Table:
+ type: component
+ description: Data table
+ DescriptionList:
+ type: component
+ description: Key-value list
+ ProgressBar:
+ type: component
+ description: Progress indicator
+ LoadingSpinner:
+ type: component
+ description: Loading state indicator
+ EmptyState:
+ type: component
+ description: Empty state placeholder
+ ErrorState:
+ type: component
+ description: Error state display
+
+ # Overlay Components
+ Modal:
+ type: component
+ description: Modal dialog
+ since: "0.10.0"
+ Panel:
+ type: component
+ description: Slide-out panel
+ since: "0.10.0"
+
+ # Form Components
+ Form:
+ type: component
+ description: Form container with validation
+
+ subpackages:
+ crm:
+ package: "@hubspot/ui-extensions/crm"
+ description: CRM-specific components that fetch data from records
+ exports:
+ CrmAssociationTable:
+ type: component
+ description: Table of associated CRM records
+ CrmPropertyList:
+ type: component
+ description: List of CRM record properties
+ CrmActionButton:
+ type: component
+ description: Button that performs CRM actions
+ CrmCardActions:
+ type: component
+ description: Card action buttons
+
+componentCatalog:
+ categories:
+ layout:
+ name: Layout
+ description: Components for organizing content
+ components: [Flex, Box, Divider, Tile]
+
+ action:
+ name: Actions
+ description: Interactive elements for user actions
+ components: [Button, ButtonRow, Link]
+
+ input:
+ name: Inputs
+ description: Form input components
+ components: [Input, TextArea, Select, DateInput, NumberInput, Toggle, Checkbox]
+
+ display:
+ name: Display
+ description: Components for showing information
+ components: [Text, Heading, Alert, Badge, Tag, Image, Table, DescriptionList]
+
+ feedback:
+ name: Feedback
+ description: Loading and state indicators
+ components: [ProgressBar, LoadingSpinner, EmptyState, ErrorState]
+
+ overlay:
+ name: Overlays
+ description: Modal and panel components
+ components: [Modal, Panel]
+
+ components:
+ Button:
+ name: Button
+ description: Primary action button with variants
+ category: action
+ sdkBinding:
+ sdk: hubspot-ui-extensions
+ export: Button
+ webStandardMapping:
+ htmlElement: button
+ ariaRole: button
+ semanticType: action
+ props:
+ variant:
+ type: string
+ enum: [primary, secondary, destructive]
+ default: primary
+ onClick:
+ type: function
+ description: Click handler
+ disabled:
+ type: boolean
+ default: false
+ type:
+ type: string
+ enum: [button, submit, reset]
+ variants:
+ - primary
+ - secondary
+ - destructive
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+
+ Modal:
+ name: Modal
+ description: Pop-up dialog for confirmations and short forms
+ category: overlay
+ sdkBinding:
+ sdk: hubspot-ui-extensions
+ export: Modal
+ webStandardMapping:
+ htmlElement: dialog
+ ariaRole: dialog
+ semanticType: container
+ props:
+ title:
+ type: string
+ description: Modal title
+ variant:
+ type: string
+ enum: [default, danger]
+ description: Use danger for destructive action confirmations
+ slots:
+ default:
+ description: Modal content
+ required: true
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ focusManagement: "Focus trapped within modal"
+
+ Panel:
+ name: Panel
+ description: Slide-out sidebar for complex tasks
+ category: overlay
+ sdkBinding:
+ sdk: hubspot-ui-extensions
+ export: Panel
+ webStandardMapping:
+ htmlElement: aside
+ ariaRole: complementary
+ semanticType: container
+ props:
+ title:
+ type: string
+ description: Panel header title
+ slots:
+ default:
+ description: Panel content
+ required: true
+
+policies:
+ componentRequirement:
+ level: required
+ scope: all
+ rationale: |
+ HubSpot enforces exclusive use of SDK components to ensure
+ consistent user experience and security across all extensions.
+
+ customComponents:
+ allowed: false
+ documentation: https://developers.hubspot.com/docs/platform/ui-extension-components
+ constraints: []
+
+ publishing:
+ privateApps:
+ componentRequirement: required
+ customComponentsAllowed: false
+ reviewRequired: false
+ notes: "Private apps still require SDK components"
+
+ publicApps:
+ componentRequirement: required
+ customComponentsAllowed: false
+ reviewRequired: true
+ designReviewRequired: true
+ notes: "Public apps undergo review before marketplace listing"
+
+ marketplaceApps:
+ componentRequirement: required
+ customComponentsAllowed: false
+ certificationRequired: true
+ notes: "Marketplace apps require full certification"
+
+ designGuidelines:
+ required: true
+ designSystem: "HubSpot Canvas"
+ designSystemUrl: https://canvas.hubspot.com/
+ designTokensProvided: false
+
+extensionPoints:
+ - id: crm-card
+ name: CRM Record Card
+ type: card
+ extensionType: codedComponents
+ description: Card displayed on CRM record pages
+ supportedComponents:
+ - all
+ constraints:
+ responsive: true
+ context:
+ provides:
+ - currentRecord
+ - user
+ actions:
+ - addNote
+ - createTask
+ - updateProperty
+
+ - id: crm-sidebar
+ name: CRM Sidebar Panel
+ type: sidebar
+ extensionType: codedComponents
+ description: Panel in the right sidebar of CRM records
+ supportedComponents:
+ - all
+ context:
+ provides:
+ - currentRecord
+ - associations
+ - user
+
+renderingEngines:
+ react:
+ type: react
+ name: React Rendering
+ description: All extensions render as React components
+ sandboxing:
+ iframeSandbox: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+
+jsonFormsIntegration:
+ supported: false
+ notes: "HubSpot uses its own Form component, not JSON Forms"
+
+mcpAppsIntegration:
+ supported: false
+ notes: "Not yet integrated with MCP Apps specification"
diff --git a/specs/fenestra/examples/0.1.0/mcp-apps.fenestra.yaml b/specs/fenestra/examples/0.1.0/mcp-apps.fenestra.yaml
new file mode 100644
index 0000000..1ebd223
--- /dev/null
+++ b/specs/fenestra/examples/0.1.0/mcp-apps.fenestra.yaml
@@ -0,0 +1,633 @@
+# MCP Apps Host - Fenestra Example
+#
+# This example describes an MCP-compatible AI assistant host that implements
+# the MCP Apps specification for agent-driven UI.
+#
+# MCP Apps enables AI agents to present UI to users through:
+# 1. Pre-declared templates (forms, confirmations, progress, etc.)
+# 2. Custom iframe fallback for complex UI needs
+#
+# Reference: https://blog.modelcontextprotocol.io/posts/2025-11-21-mcp-apps/
+
+fenestra: "0.1.0"
+
+info:
+ title: MCP Apps Host UI Ecosystem
+ version: "1.0.0"
+ description: |
+ Describes the UI capabilities of an MCP Apps-compatible host application.
+
+ MCP Apps extends the Model Context Protocol to enable AI-driven UI through
+ a hybrid model of pre-declared templates and custom iframe fallback.
+
+platform:
+ name: MCP Apps Host
+ vendor: Model Context Protocol
+ documentation: https://modelcontextprotocol.io/docs
+
+# =============================================================================
+# COMPONENT CATALOG
+# =============================================================================
+
+componentCatalog:
+ categories:
+ templates:
+ name: Agent UI Templates
+ description: Pre-declared templates agents can invoke
+ components:
+ - FormTemplate
+ - ConfirmationTemplate
+ - ProgressTemplate
+ - ResultTemplate
+ - ErrorTemplate
+ - ListTemplate
+ - DetailTemplate
+ - MediaTemplate
+
+ components:
+ FormTemplate:
+ name: Form Template
+ description: |
+ Structured form for collecting user input.
+ Rendered using JSON Forms from a JSON Schema definition.
+ category: templates
+ webStandardMapping:
+ htmlElement: form
+ ariaRole: form
+ semanticType: input
+ props:
+ type: object
+ properties:
+ title:
+ type: string
+ description: Form title
+ description:
+ type: string
+ description: Form description/instructions
+ schema:
+ type: object
+ description: JSON Schema defining form fields
+ uiSchema:
+ type: object
+ description: Optional JSON Forms UI Schema for layout
+ submitLabel:
+ type: string
+ default: Submit
+ cancelLabel:
+ type: string
+ default: Cancel
+ required:
+ - title
+ - schema
+
+ ConfirmationTemplate:
+ name: Confirmation Template
+ description: Yes/No or custom action confirmation dialog
+ category: templates
+ webStandardMapping:
+ htmlElement: dialog
+ ariaRole: alertdialog
+ semanticType: feedback
+ props:
+ type: object
+ properties:
+ title:
+ type: string
+ message:
+ type: string
+ confirmLabel:
+ type: string
+ default: Confirm
+ cancelLabel:
+ type: string
+ default: Cancel
+ variant:
+ type: string
+ enum: [info, warning, danger]
+ default: info
+ required:
+ - title
+ - message
+
+ ProgressTemplate:
+ name: Progress Template
+ description: Shows operation progress with optional status messages
+ category: templates
+ webStandardMapping:
+ htmlElement: progress
+ ariaRole: progressbar
+ semanticType: feedback
+ props:
+ type: object
+ properties:
+ title:
+ type: string
+ message:
+ type: string
+ progress:
+ type: number
+ minimum: 0
+ maximum: 100
+ description: Progress percentage (0-100), omit for indeterminate
+ steps:
+ type: array
+ items:
+ type: object
+ properties:
+ label:
+ type: string
+ status:
+ type: string
+ enum: [pending, active, completed, error]
+ required:
+ - title
+
+ ResultTemplate:
+ name: Result Template
+ description: Displays operation result/outcome
+ category: templates
+ webStandardMapping:
+ htmlElement: article
+ ariaRole: status
+ semanticType: display
+ props:
+ type: object
+ properties:
+ title:
+ type: string
+ message:
+ type: string
+ variant:
+ type: string
+ enum: [success, warning, error, info]
+ default: success
+ data:
+ type: object
+ description: Structured result data to display
+ actions:
+ type: array
+ items:
+ type: object
+ properties:
+ label:
+ type: string
+ actionId:
+ type: string
+ required:
+ - title
+
+ ErrorTemplate:
+ name: Error Template
+ description: Displays error information with optional retry
+ category: templates
+ webStandardMapping:
+ htmlElement: div
+ ariaRole: alert
+ semanticType: feedback
+ props:
+ type: object
+ properties:
+ title:
+ type: string
+ default: Something went wrong
+ message:
+ type: string
+ code:
+ type: string
+ description: Error code for debugging
+ retryable:
+ type: boolean
+ default: false
+ retryLabel:
+ type: string
+ default: Try Again
+ required:
+ - message
+
+ ListTemplate:
+ name: List Template
+ description: Displays a list of items with optional selection
+ category: templates
+ webStandardMapping:
+ htmlElement: ul
+ ariaRole: listbox
+ semanticType: display
+ props:
+ type: object
+ properties:
+ title:
+ type: string
+ items:
+ type: array
+ items:
+ type: object
+ properties:
+ id:
+ type: string
+ title:
+ type: string
+ description:
+ type: string
+ icon:
+ type: string
+ metadata:
+ type: object
+ selectable:
+ type: boolean
+ default: false
+ multiSelect:
+ type: boolean
+ default: false
+ required:
+ - items
+
+ DetailTemplate:
+ name: Detail Template
+ description: Shows detailed information about an entity
+ category: templates
+ webStandardMapping:
+ htmlElement: article
+ ariaRole: article
+ semanticType: display
+ props:
+ type: object
+ properties:
+ title:
+ type: string
+ subtitle:
+ type: string
+ sections:
+ type: array
+ items:
+ type: object
+ properties:
+ heading:
+ type: string
+ fields:
+ type: array
+ items:
+ type: object
+ properties:
+ label:
+ type: string
+ value:
+ type: string
+ type:
+ type: string
+ enum: [text, link, code, date, currency]
+ actions:
+ type: array
+ items:
+ type: object
+ properties:
+ label:
+ type: string
+ actionId:
+ type: string
+ variant:
+ type: string
+ enum: [primary, secondary, danger]
+ required:
+ - title
+
+ MediaTemplate:
+ name: Media Template
+ description: Displays media content (images, videos, documents)
+ category: templates
+ webStandardMapping:
+ htmlElement: figure
+ ariaRole: img
+ semanticType: display
+ props:
+ type: object
+ properties:
+ title:
+ type: string
+ mediaType:
+ type: string
+ enum: [image, video, audio, document, embed]
+ src:
+ type: string
+ format: uri
+ alt:
+ type: string
+ caption:
+ type: string
+ required:
+ - mediaType
+ - src
+
+# =============================================================================
+# EXTENSION POINTS
+# =============================================================================
+
+extensionPoints:
+ - id: agent-sidebar
+ name: Agent Sidebar Panel
+ type: sidebar
+ extensionType: agentUI
+ description: |
+ Sidebar panel where AI agent displays interactive UI.
+ Agent invokes templates or opens custom iframe as needed.
+ extensionTypeConfig:
+ templates:
+ supported:
+ - form
+ - confirmation
+ - progress
+ - result
+ - error
+ - list
+ - detail
+ - media
+ definitions:
+ form:
+ name: Form Template
+ description: Collect structured user input
+ inputSchema:
+ type: object
+ properties:
+ title:
+ type: string
+ schema:
+ type: object
+ required:
+ - title
+ - schema
+ outputSchema:
+ type: object
+ properties:
+ submitted:
+ type: boolean
+ data:
+ type: object
+ rendering:
+ type: jsonForms
+ interactivity:
+ submitButton: true
+ cancelButton: true
+ events:
+ - submit
+ - cancel
+ - fieldChange
+
+ confirmation:
+ name: Confirmation Template
+ description: Confirm user action
+ inputSchema:
+ type: object
+ properties:
+ title:
+ type: string
+ message:
+ type: string
+ required:
+ - title
+ - message
+ outputSchema:
+ type: object
+ properties:
+ confirmed:
+ type: boolean
+ rendering:
+ type: platform
+ component: ConfirmationDialog
+ interactivity:
+ submitButton: true
+ cancelButton: true
+ events:
+ - confirm
+ - cancel
+
+ progress:
+ name: Progress Template
+ description: Show operation progress
+ inputSchema:
+ type: object
+ properties:
+ title:
+ type: string
+ progress:
+ type: number
+ outputSchema:
+ type: object
+ properties:
+ cancelled:
+ type: boolean
+ rendering:
+ type: platform
+ component: ProgressIndicator
+ interactivity:
+ submitButton: false
+ cancelButton: true
+ events:
+ - cancel
+
+ customUI:
+ allowed: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ sizeConstraints:
+ maxWidth: 400
+ maxHeight: 600
+ resizable: true
+
+ communication:
+ protocol: jsonRpc
+ channels:
+ - templates
+ - customUI
+ - events
+ - actions
+
+ agentCapabilities:
+ invokeTemplates: true
+ openCustomUI: true
+ receiveEvents: true
+ closeUI: true
+ chainInteractions: true
+
+ constraints:
+ maxWidth: 400
+ maxHeight: 800
+ responsive: true
+
+ context:
+ provides:
+ - conversation
+ - user
+ - recentMessages
+ actions:
+ - sendMessage
+ - executeToolCall
+ - requestPermission
+
+ - id: agent-modal
+ name: Agent Modal Dialog
+ type: modal
+ extensionType: agentUI
+ description: |
+ Full-screen modal for complex agent interactions.
+ Supports all templates plus custom iframe.
+ extensionTypeConfig:
+ templates:
+ supported:
+ - form
+ - confirmation
+ - progress
+ - result
+ - error
+ - list
+ - detail
+ - media
+ customUI:
+ allowed: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ - allow-same-origin
+ sizeConstraints:
+ maxWidth: 800
+ maxHeight: 600
+ resizable: false
+ communication:
+ protocol: jsonRpc
+ channels:
+ - templates
+ - customUI
+ - events
+ agentCapabilities:
+ invokeTemplates: true
+ openCustomUI: true
+ receiveEvents: true
+ closeUI: true
+ chainInteractions: true
+
+ constraints:
+ maxWidth: 800
+ maxHeight: 600
+ responsive: true
+
+ context:
+ provides:
+ - conversation
+ - user
+ - selectedContent
+ actions:
+ - sendMessage
+ - close
+
+ - id: inline-card
+ name: Inline Card
+ type: card
+ extensionType: agentUI
+ description: |
+ Inline card within conversation for quick interactions.
+ Limited to simpler templates (no custom iframe).
+ extensionTypeConfig:
+ templates:
+ supported:
+ - result
+ - error
+ - list
+ customUI:
+ allowed: false
+ communication:
+ protocol: jsonRpc
+ channels:
+ - templates
+ - events
+ agentCapabilities:
+ invokeTemplates: true
+ openCustomUI: false
+ receiveEvents: true
+ closeUI: false
+ chainInteractions: false
+
+ constraints:
+ maxWidth: 600
+ maxHeight: 300
+ responsive: true
+
+ context:
+ provides:
+ - message
+ - toolCallId
+ actions:
+ - expandToModal
+
+# =============================================================================
+# POLICIES
+# =============================================================================
+
+policies:
+ componentRequirement:
+ level: required
+ scope: all
+ rationale: |
+ MCP Apps hosts require use of pre-declared templates to ensure
+ consistent, secure, and accessible UI across all agents.
+
+ customComponents:
+ allowed: true
+ constraints:
+ - sandboxOnly
+ registrationRequired: false
+ approvalRequired: false
+ documentation: https://modelcontextprotocol.io/docs/mcp-apps/custom-ui
+
+ publishing:
+ privateApps:
+ componentRequirement: optional
+ customComponentsAllowed: true
+ reviewRequired: false
+ notes: |
+ Private/development MCP servers have full flexibility.
+
+ publicApps:
+ componentRequirement: recommended
+ customComponentsAllowed: true
+ reviewRequired: true
+ notes: |
+ Published MCP servers should prefer templates for consistency,
+ but can use custom UI when needed.
+
+# =============================================================================
+# RENDERING ENGINES
+# =============================================================================
+
+renderingEngines:
+ templates:
+ type: mcpApps
+ name: MCP Apps Template Renderer
+ description: |
+ Renders pre-declared templates based on MCP Apps specification.
+ Uses JSON Forms for form templates, platform components for others.
+ schemaSupport:
+ dataSchema: jsonSchema
+ uiSchema: mcpAppsTemplate
+ customRenderers: false
+
+ forms:
+ type: jsonForms
+ name: JSON Forms Renderer
+ description: |
+ Renders form templates using JSON Forms specification.
+ Automatically generates UI from JSON Schema.
+ schemaSupport:
+ dataSchema: jsonSchema
+ uiSchema: jsonFormsUISchema
+ customRenderers: true
+
+ customUI:
+ type: custom
+ name: Custom Iframe Renderer
+ description: |
+ Renders custom UI in sandboxed iframe for complex interactions.
+ sandboxing:
+ iframeSandbox: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ cspPolicy: "default-src 'self'; script-src 'self'"
diff --git a/specs/fenestra/examples/0.1.0/miro.fenestra.yaml b/specs/fenestra/examples/0.1.0/miro.fenestra.yaml
new file mode 100644
index 0000000..0df4664
--- /dev/null
+++ b/specs/fenestra/examples/0.1.0/miro.fenestra.yaml
@@ -0,0 +1,279 @@
+# Fenestra Document: Miro Developer Platform
+#
+# Miro represents the "optional components" end of the spectrum.
+# The Mirotone library is provided but developers have full freedom.
+
+fenestra: "0.1.0"
+
+info:
+ title: Miro Developer Platform UI Ecosystem
+ version: "1.0.0"
+ description: |
+ Miro's Developer Platform provides the Web SDK for board interactions
+ and Mirotone as an optional CSS component library for native-feeling UIs.
+
+ Key characteristic: Component usage is OPTIONAL - developers can use
+ Mirotone, their own components, or any framework they prefer.
+
+platform:
+ name: Miro
+ vendor: Miro, Inc.
+ documentation: https://developers.miro.com/
+ appMarketplace: https://miro.com/marketplace/
+
+sdks:
+ miro-web-sdk:
+ name: Miro Web SDK
+ packageManager: npm
+ package: "@mirohq/websdk-types"
+ documentation: https://developers.miro.com/docs/miro-web-sdk-introduction
+ exports:
+ miro:
+ type: utility
+ description: Global miro object for board interactions
+
+ mirotone:
+ name: Mirotone CSS Library
+ packageManager: npm
+ package: "mirotone"
+ repository: https://github.com/miroapp/mirotone
+ documentation: https://www.mirotone.xyz/
+ description: |
+ Lightweight CSS component library that styles HTML to match Miro's UI.
+ Unlike React component libraries, Mirotone works with plain HTML.
+ exports:
+ # Mirotone uses CSS classes, not component exports
+ # Listed here for documentation purposes
+ button:
+ type: component
+ description: ".button class for buttons"
+ input:
+ type: component
+ description: ".input class for text inputs"
+ select:
+ type: component
+ description: ".select class for dropdowns"
+ checkbox:
+ type: component
+ description: ".checkbox class for checkboxes"
+ radio:
+ type: component
+ description: ".radio class for radio buttons"
+ tabs:
+ type: component
+ description: ".tabs class for tab navigation"
+ tooltip:
+ type: component
+ description: ".tooltip class for tooltips"
+ modal:
+ type: component
+ description: ".modal class for modal dialogs"
+
+componentCatalog:
+ categories:
+ action:
+ name: Actions
+ description: Interactive elements
+ components: [button]
+
+ input:
+ name: Inputs
+ description: Form controls
+ components: [input, select, checkbox, radio, textarea]
+
+ navigation:
+ name: Navigation
+ description: Navigation components
+ components: [tabs, sidebar]
+
+ overlay:
+ name: Overlays
+ description: Modal and tooltip components
+ components: [modal, tooltip]
+
+ components:
+ button:
+ name: Button
+ description: Mirotone button styling
+ category: action
+ sdkBinding:
+ sdk: mirotone
+ export: button
+ webStandardMapping:
+ htmlElement: button
+ ariaRole: button
+ semanticType: action
+ props:
+ class:
+ type: string
+ description: "CSS class: .button, .button.button-primary, .button.button-danger"
+ variants:
+ - default
+ - primary
+ - secondary
+ - danger
+ examples:
+ - title: Primary Button
+ code: |
+
+ language: html
+ - title: Icon Button
+ code: |
+
+ language: html
+
+ modal:
+ name: Modal
+ description: Mirotone modal dialog
+ category: overlay
+ sdkBinding:
+ sdk: mirotone
+ export: modal
+ webStandardMapping:
+ htmlElement: dialog
+ ariaRole: dialog
+ semanticType: container
+ examples:
+ - title: Basic Modal
+ code: |
+
+ language: html
+
+policies:
+ componentRequirement:
+ level: optional
+ scope: all
+ rationale: |
+ Miro provides Mirotone as a convenience library but does not
+ require its use. Developers have complete freedom in their
+ UI implementation choices.
+
+ customComponents:
+ allowed: true
+ constraints: []
+ registrationRequired: false
+ approvalRequired: false
+ documentation: https://developers.miro.com/docs/build-and-deploy-your-app
+
+ publishing:
+ privateApps:
+ componentRequirement: optional
+ customComponentsAllowed: true
+ reviewRequired: false
+ notes: "Complete freedom for private apps"
+
+ publicApps:
+ componentRequirement: optional
+ customComponentsAllowed: true
+ reviewRequired: true
+ notes: "Review focuses on functionality, not UI implementation"
+
+ marketplaceApps:
+ componentRequirement: optional
+ customComponentsAllowed: true
+ certificationRequired: true
+ notes: "Certification covers security and functionality"
+
+ designGuidelines:
+ required: false
+ designSystem: "Mirotone"
+ designSystemUrl: https://www.mirotone.xyz/
+ designTokensProvided: true
+
+extensionPoints:
+ - id: app-panel
+ name: App Panel
+ type: panel
+ extensionType: iframe
+ description: Panel that opens from the app icon in the left toolbar
+ supportedComponents:
+ - all
+ constraints:
+ maxWidth: 320
+ responsive: false
+ context:
+ provides:
+ - selectedItems
+ - viewport
+ - board
+ - user
+ actions:
+ - createItem
+ - updateItem
+ - deleteItem
+ - zoomTo
+
+ - id: modal
+ name: Modal Dialog
+ type: modal
+ extensionType: iframe
+ description: Full modal overlay opened via SDK
+ supportedComponents:
+ - all
+ constraints:
+ maxWidth: 600
+ maxHeight: 400
+ responsive: true
+ context:
+ provides:
+ - selectedItems
+ - board
+ - user
+
+ - id: board-item
+ name: Board Item
+ type: canvas
+ extensionType: iframe
+ description: Custom items rendered on the board canvas
+ supportedComponents:
+ - iframe-based
+ constraints:
+ responsive: true
+ context:
+ provides:
+ - itemData
+ - board
+ - user
+
+renderingEngines:
+ html-css:
+ type: custom
+ name: HTML + CSS
+ description: Plain HTML styled with Mirotone CSS classes
+
+ any-framework:
+ type: custom
+ name: Any Framework
+ description: React, Vue, Svelte, vanilla JS - developer's choice
+ sandboxing:
+ iframeSandbox: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ - allow-same-origin
+
+jsonFormsIntegration:
+ supported: true
+ rendererSet: custom
+ customRenderersAllowed: true
+ notes: "Developers can integrate JSON Forms with their own renderers"
+
+mcpAppsIntegration:
+ supported: false
+ notes: "Potential future integration via iframe embedding"
diff --git a/specs/fenestra/examples/0.1.0/salesforce.fenestra.yaml b/specs/fenestra/examples/0.1.0/salesforce.fenestra.yaml
new file mode 100644
index 0000000..9f7a952
--- /dev/null
+++ b/specs/fenestra/examples/0.1.0/salesforce.fenestra.yaml
@@ -0,0 +1,1118 @@
+# Fenestra Document: Salesforce Lightning Web Components (LWC)
+#
+# Salesforce LWC represents a component-based ecosystem with both required base
+# components and the flexibility to create custom components following strict
+# guidelines and security policies.
+
+fenestra: "0.1.0"
+
+info:
+ title: Salesforce Lightning Web Components Ecosystem
+ version: "1.0.0"
+ description: |
+ Salesforce Lightning Web Components (LWC) is a modern framework for building
+ enterprise applications on the Salesforce Platform using standard Web Components.
+
+ LWC leverages core Web Components standards (Custom Elements, Shadow DOM,
+ Templates, and ES Modules) to deliver fast, standards-based components that
+ work seamlessly within Salesforce's Lightning Experience and Experience Cloud.
+
+ Key characteristics:
+ - Built on Web Components standards
+ - Required use of Salesforce Lightning Design System (SLDS) for AppExchange apps
+ - Extensive base component library (lightning namespace)
+ - Strict security model with LockerService
+ - Governor limits enforce efficient code
+ - Mandatory security review for AppExchange publication
+
+platform:
+ name: Salesforce Platform
+ vendor: Salesforce, Inc.
+ documentation: https://developer.salesforce.com/docs/platform/lwc/overview
+ componentLibrary: https://developer.salesforce.com/docs/component-library
+ appMarketplace: https://appexchange.salesforce.com/
+ designSystem: https://www.lightningdesignsystem.com/
+
+sdks:
+ lightning-base-components:
+ name: Lightning Base Components
+ packageManager: salesforce
+ package: lightning/*
+ version: API 60.0
+ documentation: https://developer.salesforce.com/docs/component-library/overview/components
+ description: |
+ Base components provided by Salesforce in the lightning namespace.
+ These components are automatically available in all LWC components.
+ exports:
+ # Action Components
+ lightning-button:
+ type: component
+ description: Standard button with multiple variants
+ category: action
+ lightning-button-icon:
+ type: component
+ description: Icon-only button
+ category: action
+ lightning-button-group:
+ type: component
+ description: Group of related buttons
+ category: action
+ lightning-button-menu:
+ type: component
+ description: Dropdown menu button
+ category: action
+ lightning-button-stateful:
+ type: component
+ description: Button with selected/unselected states
+ category: action
+
+ # Input Components
+ lightning-input:
+ type: component
+ description: Input field supporting multiple types (text, number, email, etc.)
+ category: input
+ lightning-textarea:
+ type: component
+ description: Multi-line text input
+ category: input
+ lightning-combobox:
+ type: component
+ description: Dropdown selection with search
+ category: input
+ lightning-dual-listbox:
+ type: component
+ description: Dual list selection
+ category: input
+ lightning-checkbox-group:
+ type: component
+ description: Group of checkboxes
+ category: input
+ lightning-radio-group:
+ type: component
+ description: Radio button group
+ category: input
+ lightning-slider:
+ type: component
+ description: Range slider input
+ category: input
+ lightning-input-field:
+ type: component
+ description: Field-aware input for record forms
+ category: input
+
+ # Display Components
+ lightning-card:
+ type: component
+ description: Container with header, body, and footer
+ category: display
+ lightning-accordion:
+ type: component
+ description: Collapsible sections
+ category: display
+ lightning-avatar:
+ type: component
+ description: User or entity avatar
+ category: display
+ lightning-badge:
+ type: component
+ description: Status or label badge
+ category: display
+ lightning-pill:
+ type: component
+ description: Removable tag or label
+ category: display
+ lightning-formatted-text:
+ type: component
+ description: Display formatted text
+ category: display
+ lightning-formatted-number:
+ type: component
+ description: Display formatted numbers
+ category: display
+ lightning-formatted-date-time:
+ type: component
+ description: Display formatted dates and times
+ category: display
+ lightning-formatted-email:
+ type: component
+ description: Display email with mailto link
+ category: display
+ lightning-formatted-phone:
+ type: component
+ description: Display phone with tel link
+ category: display
+ lightning-formatted-url:
+ type: component
+ description: Display formatted URL
+ category: display
+ lightning-icon:
+ type: component
+ description: Display SLDS icons
+ category: display
+ lightning-progress-indicator:
+ type: component
+ description: Step-based progress indicator
+ category: display
+ lightning-progress-bar:
+ type: component
+ description: Linear progress bar
+ category: display
+ lightning-spinner:
+ type: component
+ description: Loading spinner
+ category: display
+
+ # Data Display Components
+ lightning-datatable:
+ type: component
+ description: Rich data table with sorting, inline editing
+ category: data
+ lightning-tree:
+ type: component
+ description: Hierarchical tree view
+ category: data
+ lightning-tree-grid:
+ type: component
+ description: Tree view with data table features
+ category: data
+
+ # Layout Components
+ lightning-layout:
+ type: component
+ description: Grid-based layout container
+ category: layout
+ lightning-layout-item:
+ type: component
+ description: Item within lightning-layout
+ category: layout
+ lightning-tab:
+ type: component
+ description: Tab within tabset
+ category: layout
+ lightning-tabset:
+ type: component
+ description: Tabbed interface
+ category: layout
+ lightning-vertical-navigation:
+ type: component
+ description: Vertical navigation menu
+ category: layout
+
+ # Record Components
+ lightning-record-form:
+ type: component
+ description: Automatic record create/edit/view form
+ category: record
+ lightning-record-edit-form:
+ type: component
+ description: Customizable record edit form
+ category: record
+ lightning-record-view-form:
+ type: component
+ description: Customizable record view form
+ category: record
+ lightning-output-field:
+ type: component
+ description: Display field value with formatting
+ category: record
+
+ # Overlay Components
+ lightning-modal:
+ type: component
+ description: Modal dialog (API 58.0+)
+ category: overlay
+ since: "API 58.0"
+
+ # Navigation
+ lightning-navigation:
+ type: component
+ description: Navigate to pages within Salesforce
+ category: navigation
+
+ # Messaging
+ lightning-messages:
+ type: component
+ description: Display field-level error messages
+ category: messaging
+
+ # Map
+ lightning-map:
+ type: component
+ description: Display map with markers
+ category: display
+
+ lightning-ui-api:
+ name: Lightning UI API Modules
+ packageManager: salesforce
+ package: lightning/ui*Api
+ version: API 60.0
+ documentation: https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reference_ui_api
+ description: |
+ Wire adapters and functions for working with Salesforce data declaratively.
+ These modules provide reactive data access with automatic caching.
+ exports:
+ # Record APIs
+ getRecord:
+ type: wireAdapter
+ module: lightning/uiRecordApi
+ description: Get record data reactively
+ getRecords:
+ type: wireAdapter
+ module: lightning/uiRecordApi
+ description: Get multiple records
+ createRecord:
+ type: function
+ module: lightning/uiRecordApi
+ description: Create a new record
+ updateRecord:
+ type: function
+ module: lightning/uiRecordApi
+ description: Update existing record
+ deleteRecord:
+ type: function
+ module: lightning/uiRecordApi
+ description: Delete a record
+ getFieldValue:
+ type: function
+ module: lightning/uiRecordApi
+ description: Extract field value from record
+ getFieldDisplayValue:
+ type: function
+ module: lightning/uiRecordApi
+ description: Get formatted field value
+
+ # List APIs
+ getListUi:
+ type: wireAdapter
+ module: lightning/uiListApi
+ description: Get list view data
+
+ # Object APIs
+ getObjectInfo:
+ type: wireAdapter
+ module: lightning/uiObjectInfoApi
+ description: Get object metadata
+ getPicklistValues:
+ type: wireAdapter
+ module: lightning/uiObjectInfoApi
+ description: Get picklist values
+ getPicklistValuesByRecordType:
+ type: wireAdapter
+ module: lightning/uiObjectInfoApi
+ description: Get picklist values for record type
+
+ lightning-platform:
+ name: Lightning Platform Modules
+ packageManager: salesforce
+ package: lightning/platform*
+ version: API 60.0
+ documentation: https://developer.salesforce.com/docs/platform/lwc/guide
+ description: |
+ Platform services for navigation, messaging, and resource loading.
+ exports:
+ # Navigation
+ NavigationMixin:
+ type: mixin
+ module: lightning/navigation
+ description: Navigate to pages, records, and external URLs
+ category: navigation
+
+ # Messaging
+ publish:
+ type: function
+ module: lightning/messageService
+ description: Publish Lightning Message Service message
+ category: messaging
+ subscribe:
+ type: function
+ module: lightning/messageService
+ description: Subscribe to Lightning Message Service channel
+ category: messaging
+ unsubscribe:
+ type: function
+ module: lightning/messageService
+ description: Unsubscribe from message channel
+ category: messaging
+ createMessageContext:
+ type: function
+ module: lightning/messageService
+ description: Create message context
+ category: messaging
+
+ # Resource Loading
+ loadStyle:
+ type: function
+ module: lightning/platformResourceLoader
+ description: Load CSS from static resources
+ category: resource
+ loadScript:
+ type: function
+ module: lightning/platformResourceLoader
+ description: Load JavaScript from static resources
+ category: resource
+
+ # Notifications
+ ShowToastEvent:
+ type: event
+ module: lightning/platformShowToastEvent
+ description: Display toast notification
+ category: messaging
+
+ # Refresh
+ RefreshEvent:
+ type: event
+ module: lightning/refresh
+ description: Trigger standard refresh (API 59.0+)
+ category: event
+ since: "API 59.0"
+
+ salesforce-lightning-design-system:
+ name: Salesforce Lightning Design System (SLDS)
+ packageManager: npm
+ package: "@salesforce-ux/design-system"
+ version: "^2.24.0"
+ repository: https://github.com/salesforce-ux/design-system
+ documentation: https://www.lightningdesignsystem.com/
+ description: |
+ The design system for Salesforce Lightning. Provides CSS framework,
+ design tokens, icons, and design guidelines. Required for AppExchange apps.
+ exports:
+ # Design Tokens
+ design-tokens:
+ type: designTokens
+ description: SLDS design tokens for colors, spacing, typography
+
+ # Icons
+ standard-icons:
+ type: iconSet
+ description: Standard object icons
+ utility-icons:
+ type: iconSet
+ description: Utility action icons
+ custom-icons:
+ type: iconSet
+ description: Custom app icons
+ action-icons:
+ type: iconSet
+ description: Action icons
+ doctype-icons:
+ type: iconSet
+ description: Document type icons
+
+ # CSS Framework
+ slds-core:
+ type: css
+ description: Core SLDS CSS framework
+
+componentCatalog:
+ categories:
+ action:
+ name: Action
+ description: Buttons and actionable elements
+ components:
+ - lightning-button
+ - lightning-button-icon
+ - lightning-button-group
+ - lightning-button-menu
+ - lightning-button-stateful
+
+ input:
+ name: Input
+ description: Form input components
+ components:
+ - lightning-input
+ - lightning-textarea
+ - lightning-combobox
+ - lightning-dual-listbox
+ - lightning-checkbox-group
+ - lightning-radio-group
+ - lightning-slider
+ - lightning-input-field
+
+ display:
+ name: Display
+ description: Components for displaying content
+ components:
+ - lightning-card
+ - lightning-accordion
+ - lightning-avatar
+ - lightning-badge
+ - lightning-pill
+ - lightning-formatted-text
+ - lightning-formatted-number
+ - lightning-formatted-date-time
+ - lightning-icon
+ - lightning-progress-indicator
+ - lightning-progress-bar
+ - lightning-spinner
+ - lightning-map
+
+ data:
+ name: Data Display
+ description: Complex data visualization components
+ components:
+ - lightning-datatable
+ - lightning-tree
+ - lightning-tree-grid
+
+ layout:
+ name: Layout
+ description: Layout and structure components
+ components:
+ - lightning-layout
+ - lightning-layout-item
+ - lightning-tab
+ - lightning-tabset
+ - lightning-vertical-navigation
+
+ record:
+ name: Record
+ description: Salesforce record management components
+ components:
+ - lightning-record-form
+ - lightning-record-edit-form
+ - lightning-record-view-form
+ - lightning-output-field
+
+ overlay:
+ name: Overlay
+ description: Modal and overlay components
+ components:
+ - lightning-modal
+
+ components:
+ lightning-button:
+ name: Lightning Button
+ description: |
+ Standard button component with support for multiple variants, icons,
+ and accessibility features. Automatically styled per SLDS guidelines.
+ category: action
+ sdkBinding:
+ sdk: lightning-base-components
+ export: lightning-button
+ webStandardMapping:
+ htmlElement: button
+ ariaRole: button
+ semanticType: action
+ props:
+ label:
+ type: string
+ description: Button label text
+ variant:
+ type: string
+ enum: [base, neutral, brand, brand-outline, destructive, destructive-text, inverse, success]
+ default: neutral
+ description: Visual variant of the button
+ type:
+ type: string
+ enum: [button, submit, reset]
+ default: button
+ disabled:
+ type: boolean
+ default: false
+ icon-name:
+ type: string
+ description: SLDS icon name
+ icon-position:
+ type: string
+ enum: [left, right]
+ default: left
+ variants:
+ - base
+ - neutral
+ - brand
+ - brand-outline
+ - destructive
+ - destructive-text
+ - inverse
+ - success
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ ariaSupport: true
+
+ lightning-datatable:
+ name: Lightning Datatable
+ description: |
+ Advanced data table with sorting, inline editing, row selection,
+ and custom cell rendering. Supports large datasets with virtualization.
+ category: data
+ sdkBinding:
+ sdk: lightning-base-components
+ export: lightning-datatable
+ webStandardMapping:
+ htmlElement: table
+ ariaRole: grid
+ semanticType: data
+ props:
+ data:
+ type: array
+ description: Array of data objects
+ required: true
+ columns:
+ type: array
+ description: Column definitions with type, label, and field name
+ required: true
+ key-field:
+ type: string
+ description: Unique identifier field for rows
+ required: true
+ sorted-by:
+ type: string
+ description: Field name to sort by
+ sorted-direction:
+ type: string
+ enum: [asc, desc]
+ show-row-number-column:
+ type: boolean
+ default: false
+ hide-checkbox-column:
+ type: boolean
+ default: false
+ events:
+ rowselection:
+ description: Fired when row selection changes
+ rowaction:
+ description: Fired when row action is clicked
+ sort:
+ description: Fired when column sort is requested
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ ariaSupport: true
+
+ lightning-card:
+ name: Lightning Card
+ description: |
+ Container component with optional header, body, and footer sections.
+ Follows SLDS card design patterns.
+ category: display
+ sdkBinding:
+ sdk: lightning-base-components
+ export: lightning-card
+ webStandardMapping:
+ htmlElement: article
+ ariaRole: article
+ semanticType: container
+ props:
+ title:
+ type: string
+ description: Card title in header
+ icon-name:
+ type: string
+ description: SLDS icon name for header
+ slots:
+ default:
+ description: Card body content
+ required: false
+ actions:
+ description: Actions in card header
+ required: false
+ footer:
+ description: Card footer content
+ required: false
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+
+ lightning-record-form:
+ name: Lightning Record Form
+ description: |
+ Automatically generates a form for creating, editing, or viewing
+ records with field-level security, validation, and layout support.
+ category: record
+ sdkBinding:
+ sdk: lightning-base-components
+ export: lightning-record-form
+ webStandardMapping:
+ htmlElement: form
+ ariaRole: form
+ semanticType: form
+ props:
+ object-api-name:
+ type: string
+ description: API name of the Salesforce object
+ required: true
+ record-id:
+ type: string
+ description: Record ID (omit for create mode)
+ fields:
+ type: array
+ description: Array of field API names to display
+ mode:
+ type: string
+ enum: [view, edit, readonly]
+ default: edit
+ layout-type:
+ type: string
+ enum: [Compact, Full]
+ columns:
+ type: number
+ enum: [1, 2]
+ events:
+ success:
+ description: Fired when record is successfully saved
+ error:
+ description: Fired when save operation fails
+ submit:
+ description: Fired when form is submitted
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ ariaSupport: true
+
+ lightning-modal:
+ name: Lightning Modal
+ description: |
+ Modal dialog component for confirmations and focused tasks.
+ Available in API 58.0+. Extends LightningModal base class.
+ category: overlay
+ sdkBinding:
+ sdk: lightning-base-components
+ export: lightning-modal
+ webStandardMapping:
+ htmlElement: dialog
+ ariaRole: dialog
+ semanticType: overlay
+ props:
+ size:
+ type: string
+ enum: [small, medium, large]
+ default: medium
+ label:
+ type: string
+ description: Modal header label (aria-label)
+ slots:
+ default:
+ description: Modal body content
+ required: true
+ header:
+ description: Modal header content
+ required: false
+ footer:
+ description: Modal footer content
+ required: false
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ focusManagement: "Focus automatically trapped within modal"
+ ariaSupport: true
+
+extensionPoints:
+ - id: record-page
+ name: Record Page
+ type: page
+ extensionType: codedComponents
+ description: |
+ Components displayed on Lightning Record Pages. Can access current
+ record context and be configured in Lightning App Builder.
+ supportedComponents:
+ - all
+ constraints:
+ responsive: true
+ sldsRequired: true
+ context:
+ provides:
+ - recordId
+ - objectApiName
+ actions:
+ - navigateToRecord
+ - refreshView
+ - fireToast
+ configuration:
+ targets:
+ - lightning__RecordPage
+ configurable: true
+ supportsDesignAttributes: true
+
+ - id: app-page
+ name: App Page
+ type: page
+ extensionType: codedComponents
+ description: |
+ Components for custom Lightning App Pages. Can be configured
+ in Lightning App Builder and accept design attributes.
+ supportedComponents:
+ - all
+ constraints:
+ responsive: true
+ sldsRequired: true
+ context:
+ provides:
+ - pageReference
+ - user
+ actions:
+ - navigate
+ - fireToast
+ configuration:
+ targets:
+ - lightning__AppPage
+ configurable: true
+ supportsDesignAttributes: true
+
+ - id: home-page
+ name: Home Page
+ type: page
+ extensionType: codedComponents
+ description: Components displayed on Lightning Home Pages
+ supportedComponents:
+ - all
+ constraints:
+ responsive: true
+ sldsRequired: true
+ configuration:
+ targets:
+ - lightning__HomePage
+ configurable: true
+
+ - id: utility-bar
+ name: Utility Bar
+ type: utility
+ extensionType: codedComponents
+ description: |
+ Dockable utility items in the footer of Lightning Experience.
+ Useful for tools that users need constant access to.
+ supportedComponents:
+ - all
+ constraints:
+ responsive: true
+ sldsRequired: true
+ maxHeight: 480px
+ context:
+ provides:
+ - utilityAPI
+ actions:
+ - minimizeUtility
+ - maximizeUtility
+ - closeUtility
+ configuration:
+ targets:
+ - lightning__UtilityBar
+ configurable: true
+
+ - id: quick-action
+ name: Quick Action
+ type: action
+ extensionType: codedComponents
+ description: |
+ Component launched as a quick action from records or global header.
+ Typically used for creating records or performing quick tasks.
+ supportedComponents:
+ - all
+ constraints:
+ responsive: true
+ sldsRequired: true
+ context:
+ provides:
+ - recordId
+ - objectApiName
+ actions:
+ - closeAction
+ - setActionResult
+ configuration:
+ targets:
+ - lightning__QuickAction
+ configurable: false
+
+ - id: flow-screen
+ name: Flow Screen
+ type: screen
+ extensionType: codedComponents
+ description: |
+ Components usable within Flow screens. Can define input/output
+ properties for Flow variable integration.
+ supportedComponents:
+ - all
+ constraints:
+ sldsRequired: true
+ context:
+ provides:
+ - flowAPI
+ actions:
+ - validate
+ - navigateNext
+ - navigatePrevious
+ configuration:
+ targets:
+ - lightning__FlowScreen
+ configurable: true
+ supportsFlowVariables: true
+
+ - id: tab
+ name: Lightning Tab
+ type: tab
+ extensionType: codedComponents
+ description: Components that can be opened as tabs in Lightning Experience
+ supportedComponents:
+ - all
+ constraints:
+ responsive: true
+ sldsRequired: true
+ configuration:
+ targets:
+ - lightning__Tab
+ configurable: true
+
+policies:
+ componentRequirement:
+ level: recommended
+ scope: public-apps
+ rationale: |
+ Salesforce recommends using Lightning Base Components for consistency,
+ accessibility, and automatic SLDS styling. However, custom components
+ are allowed if they follow SLDS guidelines and security requirements.
+
+ For AppExchange apps, use of base components is strongly recommended
+ to pass security review and design review.
+
+ customComponents:
+ allowed: true
+ documentation: https://developer.salesforce.com/docs/platform/lwc/guide/create-components.html
+ constraints:
+ - Must follow SLDS design guidelines
+ - Must implement proper accessibility (WCAG 2.1 AA)
+ - Must use LockerService-compatible JavaScript
+ - Must respect Salesforce governor limits
+ - Cannot include security vulnerabilities (XSS, CSRF, etc.)
+ - Must handle errors gracefully
+ - Custom styling must align with SLDS tokens
+
+ publishing:
+ privateDeployment:
+ componentRequirement: recommended
+ customComponentsAllowed: true
+ reviewRequired: false
+ notes: |
+ Private deployments have full flexibility but should follow best
+ practices for maintainability and user experience.
+
+ managedPackage:
+ componentRequirement: required
+ customComponentsAllowed: true
+ reviewRequired: true
+ securityReviewRequired: true
+ notes: |
+ Managed packages require adherence to packaging best practices
+ and may undergo review depending on distribution.
+
+ appExchange:
+ componentRequirement: required
+ customComponentsAllowed: true
+ certificationRequired: true
+ securityReviewRequired: true
+ designReviewRequired: true
+ notes: |
+ AppExchange apps must pass comprehensive security review including
+ manual code review, automated scans, and penetration testing.
+ Design review ensures SLDS compliance and UX quality.
+
+ designGuidelines:
+ required: true
+ designSystem: Salesforce Lightning Design System (SLDS)
+ designSystemUrl: https://www.lightningdesignsystem.com/
+ designTokensProvided: true
+ accessibility:
+ standard: WCAG 2.1 AA
+ required: true
+ documentation: https://www.lightningdesignsystem.com/accessibility/overview/
+
+ security:
+ lockerService:
+ enabled: true
+ description: |
+ LockerService enforces security by isolating components in separate
+ namespaces, providing secure wrappers for DOM APIs, and preventing
+ access to non-published component properties.
+ documentation: https://developer.salesforce.com/docs/platform/lwc/guide/security-locker-service.html
+
+ governorLimits:
+ enforced: true
+ description: |
+ Salesforce enforces governor limits on API calls, DML operations,
+ SOQL queries, heap size, and CPU time to ensure multi-tenant performance.
+ documentation: https://developer.salesforce.com/docs/atlas.en-us.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/
+
+ contentSecurityPolicy:
+ enforced: true
+ description: |
+ Strict CSP prevents inline scripts and unsafe-eval. All JavaScript
+ must be in component bundles or secure static resources.
+
+renderingEngines:
+ lwc:
+ type: webComponents
+ name: Lightning Web Components
+ description: |
+ LWC uses native Web Components standards (Custom Elements, Shadow DOM,
+ ES Modules) with a thin performance-optimized framework layer.
+ sandboxing:
+ shadowDOM: true
+ lockerService: true
+ restrictedGlobals: true
+ secureWrappers: true
+
+ aura:
+ type: legacy
+ name: Aura Components (Legacy)
+ description: |
+ Legacy Aura framework. Can interoperate with LWC but new development
+ should use LWC. Aura components can contain LWC components.
+ deprecated: false
+ interoperability:
+ canContainLWC: true
+ canBeContainedByLWC: false
+
+extensionType: codedComponents
+
+compliance:
+ appExchangeSecurity:
+ required: true
+ level: mandatory
+ description: |
+ AppExchange Security Review is mandatory for all listings. Includes:
+ - Automated security scans (Checkmarx)
+ - Manual code review
+ - Penetration testing
+ - Privacy and data handling review
+ - Third-party library assessment
+ documentation: https://developer.salesforce.com/docs/atlas.en-us.packagingGuide.meta/packagingGuide/security_review.htm
+ requirements:
+ - No critical or high severity vulnerabilities
+ - Proper input validation and output encoding
+ - Secure authentication and authorization
+ - Encrypted data transmission
+ - Compliance with Salesforce security best practices
+ - OWASP Top 10 mitigation
+
+ accessibility:
+ required: true
+ standard: WCAG 2.1 AA
+ description: |
+ Accessibility is required for AppExchange and strongly recommended
+ for all Salesforce applications. SLDS components include built-in
+ accessibility features.
+ documentation: https://www.lightningdesignsystem.com/accessibility/overview/
+ requirements:
+ - Keyboard navigation support
+ - Screen reader compatibility
+ - Proper ARIA labels and roles
+ - Sufficient color contrast
+ - Focus management
+ - Semantic HTML structure
+
+ soc2:
+ applicable: true
+ description: |
+ Salesforce Platform maintains SOC 2 Type II certification.
+ Apps on the platform benefit from this certified infrastructure.
+ documentation: https://compliance.salesforce.com/
+
+ gdpr:
+ applicable: true
+ description: |
+ Apps must comply with GDPR when handling EU personal data.
+ Salesforce provides tools for data privacy compliance.
+ documentation: https://www.salesforce.com/gdpr/
+
+ hipaa:
+ applicable: true
+ notes: |
+ HIPAA compliance available for Salesforce orgs with signed BAA.
+ Apps handling PHI must follow additional security requirements.
+ documentation: https://www.salesforce.com/solutions/industries/healthcare/hipaa-compliance/
+
+i18n:
+ supported: true
+ framework: Translation Workbench
+ description: |
+ Salesforce provides comprehensive internationalization support through
+ Translation Workbench, Custom Labels, and automatic locale detection.
+ features:
+ customLabels:
+ supported: true
+ description: |
+ Custom Labels are text values stored centrally and translated
+ into multiple languages. Accessible in LWC via @salesforce/label.
+ documentation: https://developer.salesforce.com/docs/platform/lwc/guide/create-labels.html
+
+ translationWorkbench:
+ supported: true
+ description: |
+ Translation Workbench manages translations for custom labels,
+ field labels, picklist values, and more.
+ documentation: https://help.salesforce.com/s/articleView?id=sf.workbench_overview.htm
+
+ localeDetection:
+ automatic: true
+ description: |
+ User locale automatically detected from user preferences.
+ Components can access via $i18n wire adapter.
+
+ supportedLocales:
+ - en_US
+ - de
+ - es
+ - fr
+ - it
+ - ja
+ - ko
+ - pt_BR
+ - zh_CN
+ - zh_TW
+ - many more...
+
+ dateTimeFormatting:
+ automatic: true
+ description: |
+ lightning-formatted-date-time automatically formats dates
+ according to user locale.
+
+ numberFormatting:
+ automatic: true
+ description: |
+ lightning-formatted-number automatically formats numbers
+ and currency according to user locale.
+
+ rightToLeft:
+ supported: true
+ description: SLDS includes RTL support for Arabic, Hebrew, etc.
+
+jsonFormsIntegration:
+ supported: false
+ notes: |
+ Salesforce uses lightning-record-form and lightning-*-input components
+ rather than JSON Forms. Dynamic forms can be built with dynamic field
+ rendering.
+
+mcpAppsIntegration:
+ supported: false
+ notes: Not yet integrated with MCP Apps specification
+
+notes: |
+ Additional Salesforce LWC Considerations:
+
+ 1. Development Environment:
+ - Salesforce CLI (sf) for project creation and deployment
+ - VS Code with Salesforce Extensions recommended
+ - Local Development Server available (API 58.0+)
+
+ 2. Testing:
+ - Jest for unit testing
+ - Lightning Testing Service (LTS) for integration tests
+ - Salesforce DX scratch orgs for testing
+
+ 3. Deployment:
+ - Metadata API
+ - Change Sets
+ - Salesforce DX / Source-Driven Development
+ - CI/CD pipelines with Salesforce CLI
+
+ 4. Performance:
+ - Components lazy-loaded by default
+ - Wire service provides automatic caching
+ - Governor limits enforce efficient code
+
+ 5. Versioning:
+ - Components versioned by Salesforce API version
+ - Backward compatibility maintained
+ - API versions updated three times per year
diff --git a/specs/fenestra/examples/0.1.0/shopify.fenestra.yaml b/specs/fenestra/examples/0.1.0/shopify.fenestra.yaml
new file mode 100644
index 0000000..845fabe
--- /dev/null
+++ b/specs/fenestra/examples/0.1.0/shopify.fenestra.yaml
@@ -0,0 +1,1400 @@
+# Fenestra Document: Shopify Extensions Ecosystem
+#
+# Shopify represents a HYBRID extension ecosystem with multiple surfaces requiring
+# different integration approaches:
+#
+# 1. Admin Embedded Apps: iframe + App Bridge SDK for communication
+# 2. Checkout UI Extensions: React components with limited Checkout UI component set
+# 3. Post-purchase Extensions: React components with Checkout UI components
+# 4. POS UI Extensions: Native mobile components
+# 5. Theme App Extensions: Liquid templates + custom sections
+#
+# Key Characteristics:
+# - Multiple component catalogs for different surfaces (Polaris vs Checkout UI)
+# - Hybrid extensionType (iframe for admin, codedComponents for checkout)
+# - App Bridge for iframe-admin communication
+# - Strict App Store review for public apps
+# - Multi-language support via Shopify Markets
+# - Different security models per surface
+
+fenestra: "0.1.0"
+
+info:
+ title: Shopify Extensions Ecosystem
+ version: "1.0.0"
+ summary: Multi-surface extension platform for commerce applications
+ description: |
+ Shopify provides multiple extension surfaces for building commerce applications,
+ each with different technical approaches and component requirements:
+
+ **Admin Extensions (Embedded Apps):**
+ - Embedded in iframe within Shopify Admin
+ - Use App Bridge SDK for communication with host
+ - Polaris design system for UI consistency
+ - Full React/custom component flexibility
+
+ **Checkout UI Extensions:**
+ - React components running in sandboxed runtime
+ - Limited to Checkout UI component set (NOT Polaris)
+ - Strict performance and security requirements
+ - No iframe - direct component rendering
+
+ **Post-purchase Extensions:**
+ - React components with Checkout UI components
+ - Displayed after payment confirmation
+ - Limited time window for customer interaction
+
+ **POS UI Extensions:**
+ - Native iOS/Android components
+ - Used in Shopify POS app
+ - Touch-optimized for retail environments
+
+ **Theme App Extensions:**
+ - Liquid templates and custom sections
+ - Integrated into merchant themes
+ - No React - uses Shopify's templating language
+
+ This hybrid approach allows Shopify to balance flexibility (admin apps),
+ performance (checkout extensions), and security (sandboxed runtimes).
+
+ contact:
+ name: Shopify Developer Support
+ url: https://shopify.dev/support
+ email: developers@shopify.com
+
+platform:
+ name: Shopify
+ vendor: Shopify Inc.
+ documentation: https://shopify.dev/docs/apps
+ appMarketplace: https://apps.shopify.com/
+
+# =============================================================================
+# SDK DEFINITIONS
+# =============================================================================
+
+sdks:
+ shopify-app-bridge:
+ name: Shopify App Bridge
+ packageManager: npm
+ package: "@shopify/app-bridge"
+ version: "^3.7.0"
+ platform: web
+ documentation: https://shopify.dev/docs/api/app-bridge
+ repository: https://github.com/Shopify/app-bridge
+ installCommand: npm install @shopify/app-bridge
+ description: |
+ App Bridge enables communication between embedded admin apps (running in
+ iframes) and the Shopify Admin host. It provides a JavaScript API for:
+ - Navigation within Shopify Admin
+ - Opening modals and toasts
+ - Triggering actions (ResourcePicker, etc.)
+ - Context awareness (shop, user, etc.)
+ - TitleBar and navigation customization
+
+ App Bridge uses postMessage for secure cross-origin communication.
+
+ exports:
+ createApp:
+ type: utility
+ description: Initialize App Bridge connection
+ actions:
+ type: utility
+ description: Namespace for all App Bridge actions
+
+ subpackages:
+ actions:
+ package: "@shopify/app-bridge/actions"
+ description: App Bridge action modules
+ exports:
+ TitleBar:
+ type: utility
+ description: Customize app title bar in admin
+ Toast:
+ type: utility
+ description: Show toast notifications
+ Modal:
+ type: utility
+ description: Open modals
+ ResourcePicker:
+ type: utility
+ description: Pick products, collections, variants
+ Navigation:
+ type: utility
+ description: Navigate within Shopify Admin
+ Redirect:
+ type: utility
+ description: Redirect to URLs
+ Loading:
+ type: utility
+ description: Show/hide loading indicator
+ ContextualSaveBar:
+ type: utility
+ description: Show save/discard bar
+ Features:
+ type: utility
+ description: Check feature availability
+
+ shopify-app-bridge-react:
+ name: Shopify App Bridge React
+ packageManager: npm
+ package: "@shopify/app-bridge-react"
+ version: "^3.7.0"
+ platform: web
+ documentation: https://shopify.dev/docs/api/app-bridge/previous-versions/react-components
+ repository: https://github.com/Shopify/app-bridge
+ installCommand: npm install @shopify/app-bridge-react
+ description: |
+ React bindings for App Bridge, providing hooks and components for
+ seamless integration in React apps.
+
+ exports:
+ Provider:
+ type: component
+ description: App Bridge provider for React apps
+ useAppBridge:
+ type: hook
+ description: Access App Bridge instance
+ useNavigate:
+ type: hook
+ description: Navigate within Shopify Admin
+ TitleBar:
+ type: component
+ description: Configure title bar
+ ResourcePicker:
+ type: component
+ description: Product/collection picker
+ Modal:
+ type: component
+ description: Modal dialogs
+ Toast:
+ type: component
+ description: Toast notifications
+
+ shopify-polaris:
+ name: Shopify Polaris
+ packageManager: npm
+ package: "@shopify/polaris"
+ version: "^12.0.0"
+ platform: web
+ documentation: https://polaris.shopify.com/
+ repository: https://github.com/Shopify/polaris
+ installCommand: npm install @shopify/polaris
+ description: |
+ Polaris is Shopify's design system for building admin apps. It provides
+ React components, design tokens, and guidelines for creating consistent,
+ accessible experiences in Shopify Admin.
+
+ **IMPORTANT:** Polaris is ONLY for admin apps. Checkout extensions use
+ the separate Checkout UI component set.
+
+ exports:
+ # Layout Components
+ Page:
+ type: component
+ description: Top-level page container with header
+ Layout:
+ type: component
+ description: Page layout with sections
+ Card:
+ type: component
+ description: Content container
+ Stack:
+ type: component
+ description: Flex layout for spacing items
+
+ # Action Components
+ Button:
+ type: component
+ description: Standard button
+ ButtonGroup:
+ type: component
+ description: Group related buttons
+
+ # Form Components
+ TextField:
+ type: component
+ description: Text input field
+ Select:
+ type: component
+ description: Dropdown select
+ Checkbox:
+ type: component
+ description: Checkbox input
+ RadioButton:
+ type: component
+ description: Radio button
+ ChoiceList:
+ type: component
+ description: List of checkboxes or radios
+
+ # Data Display
+ DataTable:
+ type: component
+ description: Table for tabular data
+ ResourceList:
+ type: component
+ description: List of resources with bulk actions
+ ResourceItem:
+ type: component
+ description: Item within ResourceList
+
+ # Feedback
+ Banner:
+ type: component
+ description: Contextual messages and alerts
+ Toast:
+ type: component
+ description: Brief messages (deprecated - use App Bridge)
+ Spinner:
+ type: component
+ description: Loading indicator
+
+ # Navigation
+ Tabs:
+ type: component
+ description: Tab navigation
+
+ # Overlays
+ Modal:
+ type: component
+ description: Modal dialogs (deprecated - use App Bridge)
+ Popover:
+ type: component
+ description: Floating content
+
+ # Icons
+ Icon:
+ type: component
+ description: Icon component
+
+ checkout-ui-extensions:
+ name: Checkout UI Extensions
+ packageManager: npm
+ package: "@shopify/ui-extensions/checkout"
+ version: "^2024.10.0"
+ platform: web
+ documentation: https://shopify.dev/docs/api/checkout-ui-extensions
+ repository: https://github.com/Shopify/ui-extensions
+ installCommand: npm install @shopify/ui-extensions
+ description: |
+ Checkout UI Extensions provide a LIMITED set of React components for
+ building extensions in Shopify checkout. These components are DIFFERENT
+ from Polaris and are optimized for the checkout experience.
+
+ Key differences from Polaris:
+ - Smaller component set (performance-critical)
+ - Checkout-specific components (e.g., DeliveryOptions)
+ - No direct DOM access (sandboxed runtime)
+ - Automatic accessibility and responsive design
+ - Localization handled by Shopify
+
+ exports:
+ # Layout
+ BlockStack:
+ type: component
+ description: Vertical stack layout
+ InlineStack:
+ type: component
+ description: Horizontal inline layout
+ Grid:
+ type: component
+ description: Grid layout
+ View:
+ type: component
+ description: Generic container
+
+ # Typography
+ Text:
+ type: component
+ description: Text with semantic styles
+ Heading:
+ type: component
+ description: Heading text
+
+ # Forms
+ TextField:
+ type: component
+ description: Text input
+ Checkbox:
+ type: component
+ description: Checkbox input
+ Select:
+ type: component
+ description: Select dropdown
+
+ # Actions
+ Button:
+ type: component
+ description: Action button
+ Link:
+ type: component
+ description: Hyperlink
+
+ # Display
+ Image:
+ type: component
+ description: Image display
+ Icon:
+ type: component
+ description: Icon display
+ Badge:
+ type: component
+ description: Status badge
+
+ # Checkout-specific
+ Choice:
+ type: component
+ description: Radio or checkbox choice
+ Divider:
+ type: component
+ description: Visual separator
+
+ # Hooks
+ useExtensionApi:
+ type: hook
+ description: Access extension runtime API
+ useCartLines:
+ type: hook
+ description: Access cart line items
+ useShop:
+ type: hook
+ description: Access shop information
+ useBuyerIdentity:
+ type: hook
+ description: Access customer information
+
+ shopify-cli:
+ name: Shopify CLI
+ packageManager: npm
+ package: "@shopify/cli"
+ version: "^3.51.0"
+ documentation: https://shopify.dev/docs/api/shopify-cli
+ installCommand: npm install -g @shopify/cli
+ description: |
+ Command-line interface for building Shopify apps and extensions.
+
+ cliTool:
+ package: "@shopify/cli"
+ installCommand: npm install -g @shopify/cli
+ commands:
+ init: "shopify app init"
+ dev: "shopify app dev"
+ deploy: "shopify app deploy"
+ generate: "shopify app generate extension"
+
+# =============================================================================
+# COMPONENT CATALOG - POLARIS (Admin Apps)
+# =============================================================================
+
+componentCatalog:
+ categories:
+ admin-layout:
+ name: Admin Layout
+ description: Polaris layout components for admin apps
+ components:
+ - Page
+ - Layout
+ - Card
+ - Stack
+
+ admin-actions:
+ name: Admin Actions
+ description: Polaris action components for admin apps
+ components:
+ - Button
+ - ButtonGroup
+
+ admin-forms:
+ name: Admin Forms
+ description: Polaris form components for admin apps
+ components:
+ - TextField
+ - Select
+ - Checkbox
+ - RadioButton
+
+ admin-data:
+ name: Admin Data Display
+ description: Polaris data components for admin apps
+ components:
+ - DataTable
+ - ResourceList
+
+ checkout-layout:
+ name: Checkout Layout
+ description: Checkout UI layout components
+ components:
+ - BlockStack
+ - InlineStack
+ - Grid
+ - View
+
+ checkout-forms:
+ name: Checkout Forms
+ description: Checkout UI form components
+ components:
+ - CheckoutTextField
+ - CheckoutCheckbox
+ - CheckoutSelect
+
+ components:
+ # ==========================================================================
+ # POLARIS COMPONENTS (Admin Apps)
+ # ==========================================================================
+
+ Page:
+ name: Page
+ description: |
+ Top-level container for admin pages. Provides consistent header,
+ breadcrumbs, and action areas. Used in embedded admin apps.
+ category: admin-layout
+ sdkBinding:
+ sdk: shopify-polaris
+ export: Page
+ importPath: "@shopify/polaris"
+ webStandardMapping:
+ htmlElement: div
+ ariaRole: main
+ semanticType: container
+ props:
+ type: object
+ properties:
+ title:
+ type: string
+ description: Page title
+ required: true
+ primaryAction:
+ type: object
+ description: Primary action button config
+ secondaryActions:
+ type: array
+ description: Secondary action buttons
+ breadcrumbs:
+ type: array
+ description: Breadcrumb navigation
+ slots:
+ default:
+ description: Page content
+ required: true
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ focusManagement: Automatic heading hierarchy
+ examples:
+ - title: Basic Page
+ code: |
+ import { Page, Card } from '@shopify/polaris';
+
+ function MyPage() {
+ return (
+
+
+ Page content goes here
+
+
+ );
+ }
+ language: jsx
+
+ Card:
+ name: Card
+ description: |
+ Container for grouping related content. Polaris Card provides
+ sections, headers, and actions.
+ category: admin-layout
+ sdkBinding:
+ sdk: shopify-polaris
+ export: Card
+ importPath: "@shopify/polaris"
+ webStandardMapping:
+ htmlElement: div
+ semanticType: container
+ props:
+ type: object
+ properties:
+ title:
+ type: string
+ description: Card title
+ sectioned:
+ type: boolean
+ description: Automatically wrap content in section
+ actions:
+ type: array
+ description: Card header actions
+ examples:
+ - title: Card with Sections
+ code: |
+ import { Card } from '@shopify/polaris';
+
+
+ Order information
+
+ language: jsx
+
+ Button:
+ name: Button
+ description: Standard action button with Polaris styling
+ category: admin-actions
+ sdkBinding:
+ sdk: shopify-polaris
+ export: Button
+ importPath: "@shopify/polaris"
+ webStandardMapping:
+ htmlElement: button
+ ariaRole: button
+ semanticType: action
+ props:
+ type: object
+ properties:
+ children:
+ type: string
+ description: Button text
+ primary:
+ type: boolean
+ description: Primary button style
+ destructive:
+ type: boolean
+ description: Destructive action style
+ disabled:
+ type: boolean
+ loading:
+ type: boolean
+ description: Show loading state
+ onClick:
+ type: function
+ variants:
+ - primary
+ - plain
+ - destructive
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+
+ TextField:
+ name: TextField
+ description: Text input field with label and validation
+ category: admin-forms
+ sdkBinding:
+ sdk: shopify-polaris
+ export: TextField
+ importPath: "@shopify/polaris"
+ webStandardMapping:
+ htmlElement: input
+ ariaRole: textbox
+ semanticType: input
+ props:
+ type: object
+ properties:
+ label:
+ type: string
+ description: Input label
+ value:
+ type: string
+ description: Input value
+ onChange:
+ type: function
+ description: Change handler
+ type:
+ type: string
+ enum: [text, email, number, password, search, tel, url, date, datetime-local, month, time, week]
+ error:
+ type: string
+ description: Error message
+ helpText:
+ type: string
+ description: Help text below input
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ ariaSupport: true
+
+ DataTable:
+ name: DataTable
+ description: Table for displaying tabular data
+ category: admin-data
+ sdkBinding:
+ sdk: shopify-polaris
+ export: DataTable
+ importPath: "@shopify/polaris"
+ webStandardMapping:
+ htmlElement: table
+ ariaRole: table
+ semanticType: display
+ props:
+ type: object
+ properties:
+ columnContentTypes:
+ type: array
+ description: Content types for each column
+ headings:
+ type: array
+ description: Column headings
+ rows:
+ type: array
+ description: Table data rows
+ sortable:
+ type: array
+ description: Sortable columns
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+
+ # ==========================================================================
+ # CHECKOUT UI COMPONENTS (Different from Polaris!)
+ # ==========================================================================
+
+ BlockStack:
+ name: BlockStack
+ description: |
+ Vertical stack layout for Checkout UI extensions.
+ This is part of Checkout UI components, NOT Polaris.
+ category: checkout-layout
+ sdkBinding:
+ sdk: checkout-ui-extensions
+ export: BlockStack
+ importPath: "@shopify/ui-extensions/checkout"
+ webStandardMapping:
+ htmlElement: div
+ semanticType: layout
+ props:
+ type: object
+ properties:
+ spacing:
+ type: string
+ enum: [none, extraTight, tight, base, loose, extraLoose]
+ inlineAlignment:
+ type: string
+ enum: [start, center, end]
+ examples:
+ - title: Vertical Stack in Checkout
+ code: |
+ import { BlockStack, Text } from '@shopify/ui-extensions/checkout';
+
+
+ First item
+ Second item
+
+ language: jsx
+
+ CheckoutTextField:
+ name: TextField
+ description: |
+ Text input for Checkout UI extensions. Different implementation
+ than Polaris TextField - optimized for checkout performance.
+ category: checkout-forms
+ sdkBinding:
+ sdk: checkout-ui-extensions
+ export: TextField
+ importPath: "@shopify/ui-extensions/checkout"
+ webStandardMapping:
+ htmlElement: input
+ ariaRole: textbox
+ semanticType: input
+ props:
+ type: object
+ properties:
+ label:
+ type: string
+ value:
+ type: string
+ onChange:
+ type: function
+ error:
+ type: string
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ notes: |
+ Checkout UI components handle accessibility automatically.
+ Developers cannot modify ARIA attributes directly.
+
+ CheckoutButton:
+ name: Button
+ description: |
+ Action button for Checkout UI extensions. Limited variants compared
+ to Polaris Button to maintain checkout consistency.
+ category: checkout-actions
+ sdkBinding:
+ sdk: checkout-ui-extensions
+ export: Button
+ importPath: "@shopify/ui-extensions/checkout"
+ webStandardMapping:
+ htmlElement: button
+ ariaRole: button
+ semanticType: action
+ props:
+ type: object
+ properties:
+ onPress:
+ type: function
+ description: Press handler
+ disabled:
+ type: boolean
+ loading:
+ type: boolean
+ variants:
+ - primary
+ - secondary
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+
+# =============================================================================
+# EXTENSION POINTS
+# =============================================================================
+
+extensionPoints:
+ # ===========================================================================
+ # ADMIN EMBEDDED APP (iframe + App Bridge)
+ # ===========================================================================
+
+ - id: admin-embedded-app
+ name: Admin Embedded App
+ type: fullPage
+ extensionType: iframe
+ description: |
+ Apps embedded in Shopify Admin via iframe. Use App Bridge for
+ communication with the Shopify Admin host. Can use Polaris components
+ for consistent UI, but custom React components are also allowed.
+
+ **Key Characteristics:**
+ - Runs in iframe within Shopify Admin
+ - Uses postMessage via App Bridge for host communication
+ - Full flexibility - any React framework, custom components
+ - Polaris RECOMMENDED but not required
+ - Access to Shopify APIs via session tokens
+
+ **Different from checkout extensions:** Admin apps have more freedom
+ but less integration. Checkout extensions are rendered directly by
+ Shopify with strict component limitations.
+
+ extensionTypeConfig:
+ sandboxAttributes:
+ - allow-same-origin
+ - allow-scripts
+ - allow-forms
+
+ cspRequirements: |
+ Apps must be served over HTTPS with appropriate CSP headers.
+ Frame-ancestors must allow Shopify domains.
+
+ sizeConstraints:
+ resizable: true
+ minWidth: 320
+ minHeight: 400
+
+ communication:
+ globalObject: window.shopify
+ package: "@shopify/app-bridge"
+ cdn: https://cdn.shopify.com/shopifycloud/app-bridge.js
+
+ initialization:
+ method: createApp
+ async: true
+
+ namespaces:
+ TitleBar:
+ description: Configure app title bar
+ methods: [create, set, update]
+ Toast:
+ description: Show toast notifications
+ methods: [create, show]
+ Modal:
+ description: Open modals
+ methods: [create, open, close]
+ ResourcePicker:
+ description: Pick products/collections
+ methods: [create, subscribe]
+ Navigation:
+ description: Navigate in admin
+ methods: [navigate]
+
+ capabilities:
+ context: true
+ uiActions: true
+ dataActions: true
+ events: true
+
+ asyncPattern: promises
+
+ supportedComponents:
+ - All Polaris components
+ - Custom React components
+ - Standard HTML elements
+
+ constraints:
+ responsive: true
+ httpsRequired: true
+
+ context:
+ provides:
+ - shop
+ - apiKey
+ - host
+ - sessionToken
+ actions:
+ - navigate
+ - openModal
+ - showToast
+ - pickResource
+ - redirect
+
+ # ===========================================================================
+ # CHECKOUT UI EXTENSIONS (codedComponents - NOT iframe!)
+ # ===========================================================================
+
+ - id: checkout-ui-extension
+ name: Checkout UI Extension
+ type: embedded
+ extensionType: codedComponents
+ description: |
+ React components that run in Shopify's checkout. These are NOT iframes -
+ they're rendered directly by Shopify's checkout runtime.
+
+ **CRITICAL DIFFERENCES from Admin Apps:**
+ - NOT in iframe - runs in sandboxed JavaScript runtime
+ - MUST use Checkout UI components (NOT Polaris)
+ - Limited component set for performance
+ - No direct DOM access
+ - No external network requests from component code
+ - Automatic accessibility and localization
+ - Strict performance budgets
+
+ **Extension targets:**
+ - purchase.checkout.block.render (main checkout)
+ - purchase.checkout.shipping-option-item.render-after
+ - purchase.checkout.payment-method-list.render-after
+ - purchase.checkout.delivery-address.render-after
+
+ extensionTypeConfig:
+ sdk: checkout-ui-extensions
+ framework: react
+
+ runtime:
+ type: sandboxedIframe
+ bundling: platformBuild
+ description: |
+ Checkout extensions run in a sandboxed JavaScript runtime.
+ Shopify builds and bundles your extension code. You cannot
+ bundle third-party libraries arbitrarily.
+
+ hostInteraction:
+ package: "@shopify/ui-extensions/checkout"
+
+ initialization:
+ method: extend
+ async: false
+
+ capabilities:
+ context: true
+ uiActions: false
+ dataActions: true
+ events: true
+
+ asyncPattern: promises
+
+ supportedComponents:
+ - BlockStack
+ - InlineStack
+ - Grid
+ - View
+ - Text
+ - Heading
+ - CheckoutTextField
+ - CheckoutCheckbox
+ - CheckoutSelect
+ - CheckoutButton
+ - Link
+ - Image
+ - Icon
+ - Badge
+ - Choice
+ - Divider
+
+ constraints:
+ responsive: true
+ performanceBudget:
+ maxBundleSize: 50kb
+ maxRenderTime: 100ms
+
+ context:
+ provides:
+ - cart
+ - shop
+ - buyerIdentity
+ - settings
+ actions:
+ - applyCartLinesChange
+ - applyDiscountCodeChange
+ - applyAttributeChange
+
+ # ===========================================================================
+ # POST-PURCHASE EXTENSIONS
+ # ===========================================================================
+
+ - id: post-purchase-extension
+ name: Post-purchase Extension
+ type: fullPage
+ extensionType: codedComponents
+ description: |
+ Full-page extension shown after checkout completion. Allows merchants
+ to offer post-purchase upsells with one-click purchasing (no re-entering
+ payment info). Uses Checkout UI components.
+
+ **Constraints:**
+ - Time-limited (customer can skip after countdown)
+ - Must use Checkout UI components
+ - Can modify order with customer consent
+ - Automatic payment processing (no re-auth needed)
+
+ extensionTypeConfig:
+ sdk: checkout-ui-extensions
+ framework: react
+ runtime:
+ type: sandboxedIframe
+ bundling: platformBuild
+
+ supportedComponents:
+ - BlockStack
+ - InlineStack
+ - Text
+ - Heading
+ - CheckoutButton
+ - Image
+
+ constraints:
+ maxDuration: 60s
+ responsive: true
+
+ context:
+ provides:
+ - initialPurchase
+ - shop
+ - buyerIdentity
+ actions:
+ - updateOrder
+ - completeOrder
+
+ # ===========================================================================
+ # POS UI EXTENSIONS (Native Mobile)
+ # ===========================================================================
+
+ - id: pos-ui-extension
+ name: POS UI Extension
+ type: modal
+ extensionType: codedComponents
+ description: |
+ Native mobile components for Shopify POS (Point of Sale) app.
+ Available on iOS and Android. Used for custom workflows in retail
+ environments.
+
+ **Platform-specific:**
+ - iOS: Swift UI components
+ - Android: Jetpack Compose components
+ - NOT web-based - fully native
+
+ extensionTypeConfig:
+ framework: agnostic
+ runtime:
+ type: directExecution
+ bundling: platformBuild
+
+ supportedComponents:
+ - Native mobile components (platform-specific)
+
+ constraints:
+ responsive: false
+ touchOptimized: true
+
+ context:
+ provides:
+ - cart
+ - location
+ - staff
+ actions:
+ - addCartLine
+ - completeCheckout
+
+# =============================================================================
+# POLICIES
+# =============================================================================
+
+policies:
+ componentRequirement:
+ level: required
+ scope: checkout
+ rationale: |
+ Checkout UI extensions MUST use the provided Checkout UI component set.
+ This is non-negotiable for performance, security, and accessibility.
+
+ Admin apps SHOULD use Polaris but can use custom components with proper
+ accessibility and design considerations.
+
+ customComponents:
+ allowed: true
+ constraints:
+ - Admin apps can use custom components
+ - Checkout extensions CANNOT use custom components
+ - All custom components must be accessible (WCAG 2.1 AA)
+ - Custom components should align with Polaris design principles
+ documentation: https://shopify.dev/docs/apps/design-guidelines
+
+ publishing:
+ customApps:
+ componentRequirement: recommended
+ customComponentsAllowed: true
+ reviewRequired: false
+ notes: |
+ Custom apps (private to single merchant) have full flexibility.
+
+ publicApps:
+ componentRequirement: required
+ customComponentsAllowed: true
+ reviewRequired: true
+ designReviewRequired: false
+ accessibilityAuditRequired: true
+ notes: |
+ Public apps (installable from App Store) must pass security and
+ functionality review. Polaris usage strongly recommended.
+
+ appStoreListings:
+ componentRequirement: required
+ customComponentsAllowed: true
+ certificationRequired: false
+ securityReviewRequired: true
+ designReviewRequired: true
+ accessibilityAuditRequired: true
+ notes: |
+ Apps listed in Shopify App Store undergo comprehensive review including
+ security testing, design review, and functionality testing.
+
+ designGuidelines:
+ required: true
+ designSystem: Shopify Polaris
+ designSystemUrl: https://polaris.shopify.com/
+ designTokensProvided: true
+ scope: admin-apps
+ notes: |
+ Polaris design system is for admin apps only. Checkout extensions
+ use Checkout UI components with automatic styling.
+
+ security:
+ appBridge:
+ required: true
+ scope: admin-embedded-apps
+ description: |
+ Admin embedded apps must use App Bridge for secure communication.
+ Direct iframe manipulation or insecure postMessage patterns are
+ prohibited.
+ documentation: https://shopify.dev/docs/api/app-bridge
+
+ sessionTokens:
+ required: true
+ description: |
+ Apps must use session tokens (JWT) for authenticating API requests.
+ Session tokens are short-lived and scoped to the current shop.
+ documentation: https://shopify.dev/docs/apps/auth/oauth/session-tokens
+
+ webhooks:
+ signatureVerification: required
+ description: |
+ Apps must verify HMAC signatures on all webhook requests to ensure
+ they originated from Shopify.
+ documentation: https://shopify.dev/docs/apps/webhooks/configuration/https
+
+# =============================================================================
+# RENDERING ENGINES
+# =============================================================================
+
+renderingEngines:
+ admin-app-iframe:
+ type: custom
+ name: Admin App iframe Renderer
+ description: |
+ Admin apps run in iframes with App Bridge providing the communication
+ layer. Apps can use any web framework (React, Vue, vanilla JS, etc.)
+ as long as they integrate App Bridge.
+
+ sandboxing:
+ iframeSandbox: true
+ sandboxAttributes:
+ - allow-same-origin
+ - allow-scripts
+ - allow-forms
+ cspPolicy: |
+ Apps must be served over HTTPS and set appropriate CSP headers.
+
+ checkout-runtime:
+ type: react
+ name: Checkout Extension Runtime
+ description: |
+ Checkout extensions run in Shopify's custom React runtime. This is
+ NOT a standard iframe - it's a sandboxed JavaScript execution environment
+ with limited APIs.
+
+ **Key restrictions:**
+ - No direct DOM access
+ - No window or document globals
+ - No external network requests
+ - Limited to provided Checkout UI components
+ - Automatic tree-shaking and code splitting
+
+ sandboxing:
+ iframeSandbox: true
+ customRuntime: true
+ restrictedAPIs: true
+
+# =============================================================================
+# EXTENSIONS
+# =============================================================================
+
+x-compliance:
+ security:
+ platformCertifications:
+ - PCI DSS Level 1
+ - SOC 2 Type II
+ - ISO 27001
+
+ extensionRequirements:
+ httpsOnly: true
+ cspCompliance: true
+ noInlineScripts: false
+ noExternalScripts: false
+
+ securityReview:
+ required: true
+ scope: marketplace
+ description: |
+ Apps submitted to Shopify App Store undergo security review including:
+ - Automated vulnerability scanning
+ - Manual code review for critical apps
+ - API usage verification
+ - Webhook signature verification
+ - OAuth flow validation
+
+ dataHandling:
+ piiAllowed: true
+ piiMustEncrypt: true
+ dataRetentionPolicy: required
+
+ documentation: https://shopify.dev/docs/apps/store/security
+
+ privacy:
+ platformCompliance:
+ gdpr: true
+ ccpa: true
+
+ dataResidency:
+ available: false
+ notes: Shopify stores data in centralized regions
+
+ extensionRequirements:
+ privacyPolicyRequired: true
+ consentManagement: both
+ dataProcessingAgreement: required
+ notes: |
+ Apps must provide a privacy policy and comply with merchant's
+ customer consent settings. Apps that access customer data must
+ sign a Data Processing Agreement.
+
+ userRights:
+ dataExportSupported: true
+ dataDeletionSupported: true
+ notes: |
+ Apps must support data export and deletion requests via
+ GDPR webhooks (customers/data_request, customers/redact).
+
+ documentation: https://shopify.dev/docs/apps/store/data-protection
+
+ sharedResponsibility:
+ platformHandles:
+ - Payment processing (PCI compliance)
+ - Customer data encryption at rest
+ - Infrastructure security
+ - DDoS protection
+ - SSL/TLS certificates
+ - Checkout security and fraud prevention
+ - App Bridge security (postMessage validation)
+ - Checkout extension sandboxing
+ - Customer consent management (via Customer Privacy API)
+
+ developerHandles:
+ - App server security (HTTPS, firewalls)
+ - API credential security
+ - Webhook signature verification
+ - Session token validation
+ - Data encryption in transit (to external services)
+ - Third-party service security
+ - Privacy policy and terms of service
+ - GDPR webhook implementation (data export/deletion)
+ - Secure storage of merchant/customer data
+
+ documentation: https://shopify.dev/docs/apps/store/security/shared-responsibility
+
+x-i18n:
+ platformSupport:
+ enabled: true
+
+ availableLocales:
+ # Shopify supports 20+ languages for merchants and customers
+ - ar # Arabic
+ - cs # Czech
+ - da # Danish
+ - de # German
+ - en # English
+ - es # Spanish
+ - fi # Finnish
+ - fr # French
+ - hi # Hindi
+ - id # Indonesian
+ - it # Italian
+ - ja # Japanese
+ - ko # Korean
+ - ms # Malay
+ - nb # Norwegian
+ - nl # Dutch
+ - pl # Polish
+ - pt-BR # Portuguese (Brazil)
+ - pt-PT # Portuguese (Portugal)
+ - sv # Swedish
+ - th # Thai
+ - tr # Turkish
+ - vi # Vietnamese
+ - zh-CN # Chinese (Simplified)
+ - zh-TW # Chinese (Traditional)
+
+ localeDetection:
+ method: automatic
+ sources:
+ - Shop's primary language
+ - Customer's browser language (checkout)
+ - Admin user's language preference
+ - Shopify Markets (country-specific stores)
+
+ rtlSupport:
+ enabled: true
+ languages:
+ - ar # Arabic
+ notes: |
+ Polaris components support RTL automatically. Checkout UI components
+ handle RTL based on shop locale.
+
+ componentTranslations:
+ provided: true
+ scope: all
+ notes: |
+ Polaris and Checkout UI components include built-in translations for
+ all supported languages. Developers don't need to translate component
+ strings.
+
+ developerRequirements:
+ translationMechanism:
+ format: json
+ bundleLocation: embedded
+ notes: |
+ Apps provide translations via locale files. For admin apps,
+ use i18next or similar. For checkout extensions, use Shopify's
+ i18n API provided by the runtime.
+
+ marketplaceRequirement:
+ required: false
+ minimumLocales: []
+ notes: |
+ Multi-language support not required but recommended for global reach.
+ Apps should respect shop's primary language.
+
+ formatting:
+ dates: platform
+ numbers: platform
+ currencies: platform
+ notes: |
+ Shopify provides formatted dates, numbers, and currencies based on
+ shop locale and regional settings. Apps should use Shopify's
+ formatting APIs rather than implementing their own.
+
+ shopifyMarkets:
+ description: |
+ Shopify Markets allows merchants to sell globally with country-specific
+ pricing, languages, and domains. Apps should respect Markets settings
+ and adapt content accordingly.
+ documentation: https://shopify.dev/docs/apps/markets
+
+ documentation: https://shopify.dev/docs/apps/best-practices/internationalization
+
+# =============================================================================
+# NOTES
+# =============================================================================
+
+x-notes:
+ hybridArchitecture: |
+ Shopify's extension ecosystem is HYBRID by design:
+
+ 1. **Admin Apps (iframe + App Bridge):**
+ - Maximum flexibility for developers
+ - Polaris for consistent UI but not enforced
+ - Full web framework freedom (React, Vue, etc.)
+ - Communication via App Bridge (postMessage)
+ - Slower integration (iframe overhead)
+
+ 2. **Checkout Extensions (codedComponents):**
+ - Maximum performance and security
+ - Strict component limitations (Checkout UI only)
+ - Sandboxed runtime (no DOM access)
+ - Direct rendering by Shopify (no iframe)
+ - Automatic accessibility and localization
+
+ This hybrid approach balances:
+ - Developer flexibility (admin apps)
+ - Customer experience (checkout performance)
+ - Security (checkout sandboxing)
+ - Consistency (component requirements)
+
+ developmentTools:
+ cli: |
+ Shopify CLI (@shopify/cli) is the primary development tool:
+ - Create apps and extensions
+ - Local development with hot reload
+ - Deploy to Shopify partners dashboard
+ - Generate extension boilerplate
+
+ testing: |
+ - Admin apps: Standard web testing (Jest, Testing Library)
+ - Checkout extensions: Limited testing capabilities
+ - Shopify provides test shops for integration testing
+
+ deployment: |
+ - Extensions deployed via Shopify CLI
+ - Apps reviewed via Partners dashboard
+ - Automatic versioning and rollback support
+
+ performanceConsiderations:
+ adminApps: |
+ Admin apps run in iframes with App Bridge overhead. Best practices:
+ - Minimize postMessage calls
+ - Optimize bundle size
+ - Use code splitting
+ - Lazy load routes
+
+ checkoutExtensions: |
+ Checkout extensions have strict performance budgets:
+ - Max 50kb bundle size
+ - Max 100ms render time
+ - No blocking network requests
+ - Automatic performance monitoring
+ - Extensions that exceed budgets may be disabled
+
+ multiSurfaceSupport: |
+ Apps can provide multiple extension types:
+ - Admin embedded app for merchant configuration
+ - Checkout UI extension for customer-facing features
+ - Post-purchase extension for upsells
+ - Theme app extension for storefront integration
+ - Function extension for backend logic
+
+ Each surface has different technical requirements and component catalogs.
diff --git a/specs/fenestra/examples/0.1.0/slack.fenestra.yaml b/specs/fenestra/examples/0.1.0/slack.fenestra.yaml
new file mode 100644
index 0000000..0e73f75
--- /dev/null
+++ b/specs/fenestra/examples/0.1.0/slack.fenestra.yaml
@@ -0,0 +1,1839 @@
+# Fenestra Document: Slack Block Kit
+#
+# Slack Block Kit represents a declarative, JSON-based UI framework.
+# Apps MUST use Block Kit blocks and elements - no custom components allowed.
+
+fenestra: "0.1.0"
+
+info:
+ title: Slack Block Kit UI Framework
+ version: "2.0.0"
+ description: |
+ Block Kit is Slack's UI framework for building rich, interactive app experiences.
+ It provides a declarative JSON structure for creating messages, modals, and
+ app home interfaces.
+
+ Key characteristic: Block Kit is REQUIRED - apps must use the provided blocks
+ and interactive elements exclusively. All UI is defined as JSON structures,
+ not coded components.
+
+ contact:
+ name: Slack Platform Team
+ url: https://api.slack.com/support
+ email: developers@slack.com
+
+platform:
+ name: Slack
+ vendor: Slack Technologies, LLC (Salesforce)
+ documentation: https://api.slack.com/block-kit
+ builderTool: https://app.slack.com/block-kit-builder
+ appMarketplace: https://slack.com/apps
+ changelog: https://api.slack.com/changelog
+
+sdks:
+ slack-bolt:
+ name: Slack Bolt Framework
+ packageManager: npm
+ package: "@slack/bolt"
+ version: "^3.17.0"
+ repository: https://github.com/slackapi/bolt-js
+ documentation: https://slack.dev/bolt-js/
+ description: |
+ The Bolt framework for JavaScript provides a simple, modern interface
+ for building Slack apps with Block Kit UI.
+ exports:
+ App:
+ type: class
+ description: Main application class for Slack apps
+ BlockAction:
+ type: type
+ description: Type for block action events
+ ViewSubmitAction:
+ type: type
+ description: Type for modal view submissions
+ ViewClosedAction:
+ type: type
+ description: Type for modal view closures
+
+ slack-web-api:
+ name: Slack Web API Client
+ packageManager: npm
+ package: "@slack/web-api"
+ version: "^6.11.0"
+ repository: https://github.com/slackapi/node-slack-sdk
+ documentation: https://slack.dev/node-slack-sdk/web-api
+ description: |
+ Official Web API client for Node.js, used to call Slack APIs
+ including posting messages and opening modals with Block Kit.
+ exports:
+ WebClient:
+ type: class
+ description: Client for calling Slack Web API methods
+ ChatPostMessageArguments:
+ type: interface
+ description: Arguments for posting messages with blocks
+ ViewsOpenArguments:
+ type: interface
+ description: Arguments for opening modals with blocks
+ ViewsUpdateArguments:
+ type: interface
+ description: Arguments for updating modal views
+ ViewsPushArguments:
+ type: interface
+ description: Arguments for pushing new modal views
+
+componentCatalog:
+ categories:
+ blocks:
+ name: Layout Blocks
+ description: Container blocks that structure your app's layout
+ components:
+ - section
+ - divider
+ - image
+ - actions
+ - context
+ - input
+ - header
+ - video
+ - file
+ - rich_text
+
+ elements:
+ name: Interactive Elements
+ description: Interactive components for user input and actions
+ components:
+ - button
+ - static_select
+ - external_select
+ - users_select
+ - conversations_select
+ - channels_select
+ - multi_static_select
+ - multi_external_select
+ - multi_users_select
+ - multi_conversations_select
+ - multi_channels_select
+ - overflow
+ - datepicker
+ - timepicker
+ - datetimepicker
+ - plain_text_input
+ - email_text_input
+ - url_text_input
+ - number_input
+ - checkboxes
+ - radio_buttons
+ - rich_text_input
+ - file_input
+
+ composition:
+ name: Composition Objects
+ description: Reusable objects used within blocks and elements
+ components:
+ - text
+ - option
+ - option_group
+ - confirm
+ - conversation_filter
+ - dispatch_action_config
+ - filter
+ - trigger
+
+ components:
+ # LAYOUT BLOCKS
+
+ section:
+ name: Section Block
+ description: |
+ A section block displays text, possibly with an accessory element
+ like a button or image to the side.
+ category: blocks
+ sdkBinding:
+ type: jsonSchema
+ blockType: section
+ webStandardMapping:
+ htmlElement: section
+ ariaRole: region
+ semanticType: container
+ schema:
+ type: object
+ required: [type]
+ properties:
+ type:
+ type: string
+ const: section
+ text:
+ $ref: "#/composition/text"
+ description: Text content (markdown or plain_text)
+ block_id:
+ type: string
+ description: Unique identifier for the block
+ maxLength: 255
+ fields:
+ type: array
+ description: Array of text objects displayed in 2-column layout
+ maxItems: 10
+ items:
+ $ref: "#/composition/text"
+ accessory:
+ description: Interactive element or image shown to the right
+ oneOf:
+ - $ref: "#/elements/button"
+ - $ref: "#/elements/static_select"
+ - $ref: "#/elements/image"
+ - $ref: "#/elements/datepicker"
+ - $ref: "#/elements/overflow"
+ constraints:
+ maxTextLength: 3000
+ maxFieldsLength: 2000
+ accessibility:
+ screenReaderSupport: true
+ keyboardSupport: true
+
+ divider:
+ name: Divider Block
+ description: Visual separator between blocks
+ category: blocks
+ sdkBinding:
+ type: jsonSchema
+ blockType: divider
+ webStandardMapping:
+ htmlElement: hr
+ semanticType: separator
+ schema:
+ type: object
+ required: [type]
+ properties:
+ type:
+ type: string
+ const: divider
+ block_id:
+ type: string
+ maxLength: 255
+
+ image:
+ name: Image Block
+ description: Display an image with optional title
+ category: blocks
+ sdkBinding:
+ type: jsonSchema
+ blockType: image
+ webStandardMapping:
+ htmlElement: img
+ ariaRole: img
+ semanticType: media
+ schema:
+ type: object
+ required: [type, image_url, alt_text]
+ properties:
+ type:
+ type: string
+ const: image
+ image_url:
+ type: string
+ format: uri
+ description: URL of the image
+ maxLength: 3000
+ alt_text:
+ type: string
+ description: Alt text for accessibility
+ maxLength: 2000
+ title:
+ $ref: "#/composition/text"
+ description: Optional title (plain_text only)
+ block_id:
+ type: string
+ maxLength: 255
+ accessibility:
+ altTextRequired: true
+ screenReaderSupport: true
+
+ actions:
+ name: Actions Block
+ description: Container for interactive elements (buttons, selects, etc.)
+ category: blocks
+ sdkBinding:
+ type: jsonSchema
+ blockType: actions
+ webStandardMapping:
+ htmlElement: div
+ ariaRole: group
+ semanticType: container
+ schema:
+ type: object
+ required: [type, elements]
+ properties:
+ type:
+ type: string
+ const: actions
+ elements:
+ type: array
+ description: Interactive elements
+ minItems: 1
+ maxItems: 25
+ items:
+ oneOf:
+ - $ref: "#/elements/button"
+ - $ref: "#/elements/static_select"
+ - $ref: "#/elements/datepicker"
+ - $ref: "#/elements/timepicker"
+ - $ref: "#/elements/overflow"
+ - $ref: "#/elements/checkboxes"
+ - $ref: "#/elements/radio_buttons"
+ block_id:
+ type: string
+ maxLength: 255
+ constraints:
+ maxElements: 25
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+
+ context:
+ name: Context Block
+ description: Display contextual info with text and/or images
+ category: blocks
+ sdkBinding:
+ type: jsonSchema
+ blockType: context
+ webStandardMapping:
+ htmlElement: aside
+ ariaRole: complementary
+ semanticType: metadata
+ schema:
+ type: object
+ required: [type, elements]
+ properties:
+ type:
+ type: string
+ const: context
+ elements:
+ type: array
+ description: Text objects or images
+ minItems: 1
+ maxItems: 10
+ items:
+ oneOf:
+ - $ref: "#/composition/text"
+ - type: object
+ properties:
+ type:
+ const: image
+ image_url:
+ type: string
+ alt_text:
+ type: string
+ block_id:
+ type: string
+ maxLength: 255
+
+ input:
+ name: Input Block
+ description: Form input container for modals
+ category: blocks
+ sdkBinding:
+ type: jsonSchema
+ blockType: input
+ webStandardMapping:
+ htmlElement: div
+ ariaRole: group
+ semanticType: form_field
+ schema:
+ type: object
+ required: [type, label, element]
+ properties:
+ type:
+ type: string
+ const: input
+ label:
+ $ref: "#/composition/text"
+ description: Label for the input (plain_text only)
+ element:
+ description: Input element
+ oneOf:
+ - $ref: "#/elements/plain_text_input"
+ - $ref: "#/elements/email_text_input"
+ - $ref: "#/elements/url_text_input"
+ - $ref: "#/elements/number_input"
+ - $ref: "#/elements/static_select"
+ - $ref: "#/elements/datepicker"
+ - $ref: "#/elements/timepicker"
+ - $ref: "#/elements/checkboxes"
+ - $ref: "#/elements/radio_buttons"
+ - $ref: "#/elements/rich_text_input"
+ dispatch_action:
+ type: boolean
+ description: Dispatch payload on input change
+ block_id:
+ type: string
+ maxLength: 255
+ hint:
+ $ref: "#/composition/text"
+ description: Helpful text below the input
+ optional:
+ type: boolean
+ description: Whether input is optional
+ default: false
+ accessibility:
+ labelRequired: true
+ screenReaderSupport: true
+
+ header:
+ name: Header Block
+ description: Large header text
+ category: blocks
+ sdkBinding:
+ type: jsonSchema
+ blockType: header
+ webStandardMapping:
+ htmlElement: h1
+ ariaRole: heading
+ semanticType: heading
+ schema:
+ type: object
+ required: [type, text]
+ properties:
+ type:
+ type: string
+ const: header
+ text:
+ $ref: "#/composition/text"
+ description: Header text (plain_text only, max 150 chars)
+ block_id:
+ type: string
+ maxLength: 255
+ constraints:
+ maxTextLength: 150
+
+ video:
+ name: Video Block
+ description: Embed videos from YouTube, Vimeo, etc.
+ category: blocks
+ sdkBinding:
+ type: jsonSchema
+ blockType: video
+ webStandardMapping:
+ htmlElement: video
+ ariaRole: region
+ semanticType: media
+ schema:
+ type: object
+ required: [type, video_url, thumbnail_url, alt_text, title]
+ properties:
+ type:
+ type: string
+ const: video
+ video_url:
+ type: string
+ format: uri
+ description: Video URL
+ thumbnail_url:
+ type: string
+ format: uri
+ description: Thumbnail image URL
+ alt_text:
+ type: string
+ description: Alt text for accessibility
+ maxLength: 200
+ title:
+ $ref: "#/composition/text"
+ description: Video title (plain_text only)
+ title_url:
+ type: string
+ format: uri
+ description: Hyperlinked title URL
+ author_name:
+ type: string
+ description: Author name
+ provider_name:
+ type: string
+ description: Provider name (e.g., YouTube)
+ provider_icon_url:
+ type: string
+ format: uri
+ description:
+ $ref: "#/composition/text"
+ block_id:
+ type: string
+ maxLength: 255
+
+ file:
+ name: File Block
+ description: Display a remote file
+ category: blocks
+ sdkBinding:
+ type: jsonSchema
+ blockType: file
+ schema:
+ type: object
+ required: [type, external_id, source]
+ properties:
+ type:
+ type: string
+ const: file
+ external_id:
+ type: string
+ description: ID of the file
+ source:
+ type: string
+ description: File source (e.g., "remote")
+ block_id:
+ type: string
+ maxLength: 255
+
+ rich_text:
+ name: Rich Text Block
+ description: Display rich formatted text
+ category: blocks
+ sdkBinding:
+ type: jsonSchema
+ blockType: rich_text
+ schema:
+ type: object
+ required: [type, elements]
+ properties:
+ type:
+ type: string
+ const: rich_text
+ elements:
+ type: array
+ description: Rich text elements (sections, lists, etc.)
+ block_id:
+ type: string
+ maxLength: 255
+
+ # INTERACTIVE ELEMENTS
+
+ button:
+ name: Button Element
+ description: Interactive button for actions
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: button
+ webStandardMapping:
+ htmlElement: button
+ ariaRole: button
+ semanticType: action
+ schema:
+ type: object
+ required: [type, text, action_id]
+ properties:
+ type:
+ type: string
+ const: button
+ text:
+ $ref: "#/composition/text"
+ description: Button text (plain_text only, max 75 chars)
+ action_id:
+ type: string
+ description: Identifier for the action
+ maxLength: 255
+ url:
+ type: string
+ format: uri
+ description: URL to open when clicked
+ maxLength: 3000
+ value:
+ type: string
+ description: Value sent with interaction payload
+ maxLength: 2000
+ style:
+ type: string
+ enum: [primary, danger]
+ description: Button style (primary=green, danger=red)
+ confirm:
+ $ref: "#/composition/confirm"
+ description: Confirmation dialog before action
+ accessibility_label:
+ type: string
+ description: Label for screen readers
+ variants:
+ - default
+ - primary
+ - danger
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ labelRequired: true
+
+ static_select:
+ name: Static Select Menu
+ description: Drop-down menu with static options
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: static_select
+ webStandardMapping:
+ htmlElement: select
+ ariaRole: listbox
+ semanticType: input
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: static_select
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ description: Placeholder text (plain_text only)
+ options:
+ type: array
+ description: List of options
+ maxItems: 100
+ items:
+ $ref: "#/composition/option"
+ option_groups:
+ type: array
+ description: Grouped options
+ maxItems: 100
+ items:
+ $ref: "#/composition/option_group"
+ initial_option:
+ $ref: "#/composition/option"
+ confirm:
+ $ref: "#/composition/confirm"
+ focus_on_load:
+ type: boolean
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+
+ external_select:
+ name: External Data Select Menu
+ description: Select menu with options loaded from external source
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: external_select
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: external_select
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ initial_option:
+ $ref: "#/composition/option"
+ min_query_length:
+ type: integer
+ description: Min characters before querying
+ confirm:
+ $ref: "#/composition/confirm"
+ focus_on_load:
+ type: boolean
+
+ users_select:
+ name: User Select Menu
+ description: Select menu for choosing Slack users
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: users_select
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: users_select
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ initial_user:
+ type: string
+ description: Initially selected user ID
+ confirm:
+ $ref: "#/composition/confirm"
+ focus_on_load:
+ type: boolean
+
+ conversations_select:
+ name: Conversation Select Menu
+ description: Select menu for choosing conversations
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: conversations_select
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: conversations_select
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ initial_conversation:
+ type: string
+ default_to_current_conversation:
+ type: boolean
+ confirm:
+ $ref: "#/composition/confirm"
+ response_url_enabled:
+ type: boolean
+ filter:
+ $ref: "#/composition/conversation_filter"
+ focus_on_load:
+ type: boolean
+
+ channels_select:
+ name: Channel Select Menu
+ description: Select menu for choosing channels
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: channels_select
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: channels_select
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ initial_channel:
+ type: string
+ confirm:
+ $ref: "#/composition/confirm"
+ response_url_enabled:
+ type: boolean
+ focus_on_load:
+ type: boolean
+
+ multi_static_select:
+ name: Multi-Select Static Menu
+ description: Multi-select menu with static options
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: multi_static_select
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: multi_static_select
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ options:
+ type: array
+ maxItems: 100
+ items:
+ $ref: "#/composition/option"
+ option_groups:
+ type: array
+ items:
+ $ref: "#/composition/option_group"
+ initial_options:
+ type: array
+ items:
+ $ref: "#/composition/option"
+ confirm:
+ $ref: "#/composition/confirm"
+ max_selected_items:
+ type: integer
+ focus_on_load:
+ type: boolean
+
+ multi_external_select:
+ name: Multi-Select External Menu
+ description: Multi-select with external data source
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: multi_external_select
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: multi_external_select
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ min_query_length:
+ type: integer
+ initial_options:
+ type: array
+ items:
+ $ref: "#/composition/option"
+ confirm:
+ $ref: "#/composition/confirm"
+ max_selected_items:
+ type: integer
+ focus_on_load:
+ type: boolean
+
+ multi_users_select:
+ name: Multi-User Select Menu
+ description: Multi-select for Slack users
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: multi_users_select
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: multi_users_select
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ initial_users:
+ type: array
+ items:
+ type: string
+ confirm:
+ $ref: "#/composition/confirm"
+ max_selected_items:
+ type: integer
+ focus_on_load:
+ type: boolean
+
+ multi_conversations_select:
+ name: Multi-Conversation Select Menu
+ description: Multi-select for conversations
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: multi_conversations_select
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: multi_conversations_select
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ initial_conversations:
+ type: array
+ items:
+ type: string
+ default_to_current_conversation:
+ type: boolean
+ confirm:
+ $ref: "#/composition/confirm"
+ max_selected_items:
+ type: integer
+ filter:
+ $ref: "#/composition/conversation_filter"
+ focus_on_load:
+ type: boolean
+
+ multi_channels_select:
+ name: Multi-Channel Select Menu
+ description: Multi-select for channels
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: multi_channels_select
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: multi_channels_select
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ initial_channels:
+ type: array
+ items:
+ type: string
+ confirm:
+ $ref: "#/composition/confirm"
+ max_selected_items:
+ type: integer
+ focus_on_load:
+ type: boolean
+
+ overflow:
+ name: Overflow Menu
+ description: Menu with overflow options (ellipsis menu)
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: overflow
+ webStandardMapping:
+ ariaRole: menu
+ semanticType: action
+ schema:
+ type: object
+ required: [type, action_id, options]
+ properties:
+ type:
+ type: string
+ const: overflow
+ action_id:
+ type: string
+ maxLength: 255
+ options:
+ type: array
+ description: Menu options
+ minItems: 1
+ maxItems: 5
+ items:
+ $ref: "#/composition/option"
+ confirm:
+ $ref: "#/composition/confirm"
+
+ datepicker:
+ name: Date Picker
+ description: Calendar-based date selection
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: datepicker
+ webStandardMapping:
+ htmlElement: input
+ inputType: date
+ semanticType: input
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: datepicker
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ initial_date:
+ type: string
+ format: date
+ description: Initial date in YYYY-MM-DD format
+ confirm:
+ $ref: "#/composition/confirm"
+ focus_on_load:
+ type: boolean
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+
+ timepicker:
+ name: Time Picker
+ description: Time selection input
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: timepicker
+ webStandardMapping:
+ htmlElement: input
+ inputType: time
+ semanticType: input
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: timepicker
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ initial_time:
+ type: string
+ description: Initial time in HH:mm format
+ confirm:
+ $ref: "#/composition/confirm"
+ focus_on_load:
+ type: boolean
+ timezone:
+ type: string
+ description: IANA timezone
+
+ datetimepicker:
+ name: Date Time Picker
+ description: Combined date and time selection
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: datetimepicker
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: datetimepicker
+ action_id:
+ type: string
+ maxLength: 255
+ initial_date_time:
+ type: integer
+ description: Unix timestamp
+ confirm:
+ $ref: "#/composition/confirm"
+ focus_on_load:
+ type: boolean
+
+ plain_text_input:
+ name: Plain Text Input
+ description: Single or multi-line text input
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: plain_text_input
+ webStandardMapping:
+ htmlElement: input
+ inputType: text
+ semanticType: input
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: plain_text_input
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ initial_value:
+ type: string
+ multiline:
+ type: boolean
+ description: Enable multi-line input
+ min_length:
+ type: integer
+ description: Minimum length
+ max_length:
+ type: integer
+ description: Maximum length
+ dispatch_action_config:
+ $ref: "#/composition/dispatch_action_config"
+ focus_on_load:
+ type: boolean
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+
+ email_text_input:
+ name: Email Text Input
+ description: Email address input with validation
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: email_text_input
+ webStandardMapping:
+ htmlElement: input
+ inputType: email
+ semanticType: input
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: email_text_input
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ initial_value:
+ type: string
+ format: email
+ dispatch_action_config:
+ $ref: "#/composition/dispatch_action_config"
+ focus_on_load:
+ type: boolean
+
+ url_text_input:
+ name: URL Text Input
+ description: URL input with validation
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: url_text_input
+ webStandardMapping:
+ htmlElement: input
+ inputType: url
+ semanticType: input
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: url_text_input
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ initial_value:
+ type: string
+ format: uri
+ dispatch_action_config:
+ $ref: "#/composition/dispatch_action_config"
+ focus_on_load:
+ type: boolean
+
+ number_input:
+ name: Number Input
+ description: Numeric input with validation
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: number_input
+ webStandardMapping:
+ htmlElement: input
+ inputType: number
+ semanticType: input
+ schema:
+ type: object
+ required: [type, action_id, is_decimal_allowed]
+ properties:
+ type:
+ type: string
+ const: number_input
+ action_id:
+ type: string
+ maxLength: 255
+ is_decimal_allowed:
+ type: boolean
+ description: Allow decimal numbers
+ placeholder:
+ $ref: "#/composition/text"
+ initial_value:
+ type: string
+ description: Initial numeric value as string
+ min_value:
+ type: string
+ description: Minimum value
+ max_value:
+ type: string
+ description: Maximum value
+ dispatch_action_config:
+ $ref: "#/composition/dispatch_action_config"
+ focus_on_load:
+ type: boolean
+
+ checkboxes:
+ name: Checkboxes
+ description: Checkbox group for multiple selections
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: checkboxes
+ webStandardMapping:
+ htmlElement: input
+ inputType: checkbox
+ ariaRole: group
+ semanticType: input
+ schema:
+ type: object
+ required: [type, action_id, options]
+ properties:
+ type:
+ type: string
+ const: checkboxes
+ action_id:
+ type: string
+ maxLength: 255
+ options:
+ type: array
+ description: Checkbox options
+ minItems: 1
+ maxItems: 10
+ items:
+ $ref: "#/composition/option"
+ initial_options:
+ type: array
+ description: Pre-selected options
+ items:
+ $ref: "#/composition/option"
+ confirm:
+ $ref: "#/composition/confirm"
+ focus_on_load:
+ type: boolean
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+
+ radio_buttons:
+ name: Radio Buttons
+ description: Radio button group for single selection
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: radio_buttons
+ webStandardMapping:
+ htmlElement: input
+ inputType: radio
+ ariaRole: radiogroup
+ semanticType: input
+ schema:
+ type: object
+ required: [type, action_id, options]
+ properties:
+ type:
+ type: string
+ const: radio_buttons
+ action_id:
+ type: string
+ maxLength: 255
+ options:
+ type: array
+ description: Radio options
+ minItems: 1
+ maxItems: 10
+ items:
+ $ref: "#/composition/option"
+ initial_option:
+ $ref: "#/composition/option"
+ confirm:
+ $ref: "#/composition/confirm"
+ focus_on_load:
+ type: boolean
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+
+ rich_text_input:
+ name: Rich Text Input
+ description: Rich text editor with formatting
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: rich_text_input
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: rich_text_input
+ action_id:
+ type: string
+ maxLength: 255
+ placeholder:
+ $ref: "#/composition/text"
+ initial_value:
+ type: object
+ description: Initial rich text value
+ dispatch_action_config:
+ $ref: "#/composition/dispatch_action_config"
+ focus_on_load:
+ type: boolean
+
+ file_input:
+ name: File Input
+ description: File upload input
+ category: elements
+ sdkBinding:
+ type: jsonSchema
+ elementType: file_input
+ schema:
+ type: object
+ required: [type, action_id]
+ properties:
+ type:
+ type: string
+ const: file_input
+ action_id:
+ type: string
+ maxLength: 255
+ filetypes:
+ type: array
+ description: Allowed file extensions
+ items:
+ type: string
+ max_files:
+ type: integer
+ description: Maximum number of files
+ minimum: 1
+ maximum: 10
+
+ # COMPOSITION OBJECTS
+
+ text:
+ name: Text Object
+ description: Text with plain_text or mrkdwn formatting
+ category: composition
+ schema:
+ type: object
+ required: [type, text]
+ properties:
+ type:
+ type: string
+ enum: [plain_text, mrkdwn]
+ text:
+ type: string
+ maxLength: 3000
+ emoji:
+ type: boolean
+ description: Escape emoji codes (plain_text only)
+ verbatim:
+ type: boolean
+ description: Disable auto-linking (mrkdwn only)
+
+ option:
+ name: Option Object
+ description: Single option for select menus and overflow menus
+ category: composition
+ schema:
+ type: object
+ required: [text, value]
+ properties:
+ text:
+ $ref: "#/composition/text"
+ description: Option text (plain_text only, max 75 chars)
+ value:
+ type: string
+ description: Option value
+ maxLength: 75
+ description:
+ $ref: "#/composition/text"
+ description: Detailed description (plain_text, max 75 chars)
+ url:
+ type: string
+ format: uri
+ description: URL loaded when option selected
+
+ option_group:
+ name: Option Group
+ description: Group of options with a label
+ category: composition
+ schema:
+ type: object
+ required: [label, options]
+ properties:
+ label:
+ $ref: "#/composition/text"
+ description: Group label (plain_text only, max 75 chars)
+ options:
+ type: array
+ description: Options in the group
+ maxItems: 100
+ items:
+ $ref: "#/composition/option"
+
+ confirm:
+ name: Confirmation Dialog
+ description: Confirmation prompt before destructive actions
+ category: composition
+ schema:
+ type: object
+ required: [title, text, confirm, deny]
+ properties:
+ title:
+ $ref: "#/composition/text"
+ description: Dialog title (plain_text only, max 100 chars)
+ text:
+ $ref: "#/composition/text"
+ description: Confirmation message (max 300 chars)
+ confirm:
+ $ref: "#/composition/text"
+ description: Confirm button text (plain_text, max 30 chars)
+ deny:
+ $ref: "#/composition/text"
+ description: Deny button text (plain_text, max 30 chars)
+ style:
+ type: string
+ enum: [primary, danger]
+ description: Confirm button style
+
+ conversation_filter:
+ name: Conversation Filter
+ description: Filter for conversation lists
+ category: composition
+ schema:
+ type: object
+ properties:
+ include:
+ type: array
+ description: Conversation types to include
+ items:
+ type: string
+ enum: [im, mpim, private, public]
+ exclude_external_shared_channels:
+ type: boolean
+ exclude_bot_users:
+ type: boolean
+
+ dispatch_action_config:
+ name: Dispatch Action Config
+ description: Configuration for dispatching actions on input change
+ category: composition
+ schema:
+ type: object
+ properties:
+ trigger_actions_on:
+ type: array
+ description: When to trigger actions
+ items:
+ type: string
+ enum: [on_enter_pressed, on_character_entered]
+
+policies:
+ componentRequirement:
+ level: required
+ scope: all
+ rationale: |
+ Slack enforces exclusive use of Block Kit blocks and elements.
+ No custom UI components are allowed - all interfaces must be
+ built using the provided Block Kit JSON structure.
+
+ customComponents:
+ allowed: false
+ documentation: https://api.slack.com/block-kit
+ constraints:
+ - All UI must be defined using Block Kit JSON
+ - No custom HTML, CSS, or JavaScript
+ - Apps execute server-side; UI is rendered by Slack client
+ rationale: |
+ Block Kit ensures consistent user experience, accessibility,
+ security, and cross-platform compatibility across all Slack clients.
+
+ publishing:
+ workspace:
+ name: Workspace Apps
+ componentRequirement: required
+ customComponentsAllowed: false
+ reviewRequired: false
+ notes: |
+ Apps installed to a single workspace. Block Kit required
+ but no review process for private installations.
+
+ publicDistribution:
+ name: Public Distribution
+ componentRequirement: required
+ customComponentsAllowed: false
+ reviewRequired: true
+ securityReviewRequired: true
+ notes: |
+ Apps distributed publicly undergo App Directory review
+ including security, functionality, and UX assessment.
+
+ appDirectory:
+ name: Slack App Directory
+ componentRequirement: required
+ customComponentsAllowed: false
+ certificationRequired: false
+ reviewRequired: true
+ securityReviewRequired: true
+ notes: |
+ Listing in App Directory requires passing review.
+ Featured apps undergo additional vetting.
+
+ designGuidelines:
+ required: true
+ designSystem: Block Kit
+ designSystemUrl: https://api.slack.com/block-kit
+ builderUrl: https://app.slack.com/block-kit-builder
+ designTokensProvided: false
+ guidelines:
+ - Use Block Kit Builder to design and validate layouts
+ - Follow text length limits for each block type
+ - Provide clear, concise labels and placeholder text
+ - Use confirmation dialogs for destructive actions
+ - Ensure accessibility with alt text and labels
+
+ performance:
+ messageBlockLimit: 50
+ modalBlockLimit: 100
+ homeTabBlockLimit: 100
+ interactionTimeout: 3000
+ notes: |
+ Interactions must respond within 3 seconds. Long-running
+ operations should use response URLs for async updates.
+
+extensionPoints:
+ - id: message
+ name: Messages
+ type: surface
+ extensionType: jsonResponse
+ description: |
+ Block Kit messages in channels, DMs, or threads. The primary
+ surface for rich app interactions in conversations.
+ supportedBlocks:
+ - section
+ - divider
+ - image
+ - actions
+ - context
+ - header
+ - video
+ - file
+ - rich_text
+ constraints:
+ maxBlocks: 50
+ maxTextLength: 3000
+ supportsMarkdown: true
+ context:
+ provides:
+ - channel_id
+ - user_id
+ - team_id
+ - message_ts
+ - thread_ts
+ actions:
+ - postMessage
+ - updateMessage
+ - postEphemeral
+ documentation: https://api.slack.com/surfaces/messages
+
+ - id: modal
+ name: Modals
+ type: surface
+ extensionType: jsonResponse
+ description: |
+ Focused surfaces for data collection, confirmations, and
+ workflows. Opened via views.open API call.
+ supportedBlocks:
+ - section
+ - divider
+ - image
+ - actions
+ - context
+ - input
+ - header
+ - video
+ - rich_text
+ constraints:
+ maxBlocks: 100
+ maxInputBlocks: 100
+ canStack: true
+ maxStackDepth: 3
+ context:
+ provides:
+ - trigger_id
+ - user_id
+ - team_id
+ - view_id
+ actions:
+ - viewsOpen
+ - viewsUpdate
+ - viewsPush
+ callbacks:
+ - view_submission
+ - view_closed
+ documentation: https://api.slack.com/surfaces/modals
+
+ - id: home-tab
+ name: App Home Tab
+ type: surface
+ extensionType: jsonResponse
+ description: |
+ Personal space for users to interact with your app.
+ Accessed via the app's Home tab.
+ supportedBlocks:
+ - section
+ - divider
+ - image
+ - actions
+ - context
+ - header
+ - video
+ - rich_text
+ constraints:
+ maxBlocks: 100
+ noInputBlocks: true
+ refreshable: true
+ context:
+ provides:
+ - user_id
+ - team_id
+ - view_id
+ actions:
+ - viewsPublish
+ callbacks:
+ - app_home_opened
+ documentation: https://api.slack.com/surfaces/app-home
+
+ - id: workflow-step
+ name: Workflow Steps
+ type: surface
+ extensionType: jsonResponse
+ description: |
+ Custom steps in Workflow Builder. Includes configuration
+ modal and execution logic.
+ supportedBlocks:
+ - section
+ - divider
+ - actions
+ - context
+ - input
+ - header
+ constraints:
+ configurationRequired: true
+ executionAsync: true
+ context:
+ provides:
+ - workflow_step_id
+ - inputs
+ - outputs
+ actions:
+ - workflowStepEdit
+ - workflowsUpdateStep
+ callbacks:
+ - workflow_step_edit
+ - workflow_step_execute
+ documentation: https://api.slack.com/workflows/steps
+
+renderingEngines:
+ slack-native:
+ type: native
+ name: Slack Native Rendering
+ description: |
+ Block Kit is rendered natively by Slack clients (desktop, mobile, web).
+ Apps define UI as JSON; Slack handles all rendering and interactions.
+ sandboxing:
+ serverSideExecution: true
+ clientSideExecution: false
+ notes: |
+ App logic runs on developer servers. Slack clients send
+ interaction payloads to registered endpoints.
+ platforms:
+ - Slack Desktop (Windows, macOS, Linux)
+ - Slack Mobile (iOS, Android)
+ - Slack Web
+
+jsonFormsIntegration:
+ supported: false
+ notes: |
+ Block Kit has its own input/form system with the input block
+ and various input elements. Not compatible with JSON Forms.
+
+mcpAppsIntegration:
+ supported: false
+ notes: Not yet integrated with MCP Apps specification
+
+extensionType: jsonResponse
+
+extensions:
+ declarativeSchemas:
+ enabled: true
+ schemaFormat: json
+ description: |
+ Block Kit is entirely JSON-based. Apps construct blocks and
+ elements as JSON objects conforming to Block Kit schemas.
+ validation:
+ builderTool: https://app.slack.com/block-kit-builder
+ sdkValidation: true
+ runtimeValidation: true
+ schemaDocumentation: https://api.slack.com/reference/block-kit/blocks
+
+ i18n:
+ enabled: true
+ localeDetection: automatic
+ description: |
+ Slack provides user locale information. Apps can localize
+ Block Kit text content based on user preferences.
+ implementation:
+ clientProvides:
+ - user_locale
+ - team_locale
+ developerResponsibility:
+ - Translate text objects
+ - Handle RTL languages
+ - Format dates/times appropriately
+ supportedLocales:
+ - en-US
+ - en-GB
+ - de-DE
+ - es-ES
+ - es-LA
+ - fr-FR
+ - it-IT
+ - ja-JP
+ - ko-KR
+ - pt-BR
+ - ru-RU
+ - zh-CN
+ - zh-TW
+ documentation: https://api.slack.com/reference/internationalization
+
+ compliance:
+ enabled: true
+ description: |
+ Apps distributed publicly must comply with Slack's App
+ Directory Review requirements and security standards.
+ requirements:
+ securityReview:
+ required: true
+ scope: publicDistribution
+ includes:
+ - Data handling and privacy review
+ - OAuth implementation verification
+ - Secure API usage patterns
+ - Permission scope audit
+ functionalReview:
+ required: true
+ scope: appDirectory
+ includes:
+ - App functionality testing
+ - Error handling validation
+ - User experience assessment
+ contentReview:
+ required: true
+ scope: appDirectory
+ includes:
+ - App listing content
+ - Screenshots and media
+ - Privacy policy and terms
+ certifications:
+ dataResidency:
+ available: true
+ description: Data Residency certification for regulated industries
+ enterpriseKeyManagement:
+ available: true
+ description: EKM support for enterprise customers
+ documentation: https://api.slack.com/start/distributing/directory
+ privacyPolicy: https://slack.com/privacy-policy
+
+ analytics:
+ enabled: true
+ description: |
+ Slack provides analytics for app usage, installations,
+ and user engagement within the Slack platform.
+ metrics:
+ - Daily/Monthly Active Users
+ - Message interactions
+ - Modal opens and submissions
+ - App Home views
+ - Installation/uninstallation rates
+ dashboard: https://api.slack.com/apps (App Management)
+
+ testing:
+ enabled: true
+ description: Tools and methods for testing Block Kit interfaces
+ tools:
+ blockKitBuilder:
+ url: https://app.slack.com/block-kit-builder
+ description: Visual builder with live preview and validation
+ features:
+ - Visual block composition
+ - JSON export/import
+ - Sample payload generation
+ - Validation errors
+ slackPlatformSimulator:
+ description: Test apps in development workspace
+ features:
+ - Real-time interaction testing
+ - Event simulation
+ - Permission testing
+ documentation: https://api.slack.com/block-kit/building
+
+ accessibilityFeatures:
+ keyboardNavigation: true
+ screenReaderSupport: true
+ highContrastMode: true
+ description: |
+ Block Kit is designed with accessibility built-in. Slack
+ clients handle keyboard navigation, screen reader support,
+ and high contrast modes automatically.
+ guidelines:
+ - Provide alt text for all images
+ - Use descriptive button labels
+ - Include accessibility_label for complex elements
+ - Ensure logical focus order in modals
+ documentation: https://api.slack.com/block-kit/accessibility
+
+ rateLimits:
+ description: Rate limits for Slack API methods
+ limits:
+ chatPostMessage:
+ tier1: 1 per second
+ tier2: 20 per minute
+ tier3: 50+ per minute (varies by workspace)
+ viewsOpen:
+ rate: 3 per second per user
+ viewsUpdate:
+ rate: 3 per second per view
+ viewsPublish:
+ rate: 5 per minute per user
+ documentation: https://api.slack.com/docs/rate-limits
+
+ securityFeatures:
+ oauthRequired: true
+ scopedPermissions: true
+ requestSigning: true
+ description: |
+ Slack apps use OAuth 2.0 for authentication with granular
+ permission scopes. All requests are signed and verified.
+ features:
+ - Request signature verification
+ - Token rotation support
+ - App-level tokens
+ - User tokens vs bot tokens
+ - Workspace app management
+ documentation: https://api.slack.com/authentication
+
+notes: |
+ Slack Block Kit is a comprehensive, JSON-based UI framework that enforces
+ a strict component model. Apps cannot use custom UI components - all
+ interfaces must be built using Block Kit's declarative structure.
+
+ Key characteristics:
+ - Fully declarative: UI defined as JSON, not code
+ - Server-side execution: App logic runs on developer servers
+ - Native rendering: Slack clients render Block Kit natively
+ - Cross-platform: Consistent across desktop, mobile, and web
+ - Accessibility built-in: Keyboard, screen reader support automatic
+ - Interactive: Rich interactions via action handlers
+
+ Block Kit is used across all Slack surfaces: messages, modals, Home tabs,
+ and workflow steps. The Block Kit Builder provides visual design and
+ validation tools for developers.
+
+metadata:
+ fenestra:
+ createdAt: "2025-12-30"
+ author: "Fenestra Specification Team"
+ category: "Communication Platform"
+ tags:
+ - messaging
+ - collaboration
+ - json-ui
+ - declarative
+ - block-kit
+ relatedPlatforms:
+ - Microsoft Teams (Adaptive Cards)
+ - Discord (Embeds)
+ - Webex (Cards)
diff --git a/specs/fenestra/examples/0.1.0/stripe.fenestra.yaml b/specs/fenestra/examples/0.1.0/stripe.fenestra.yaml
new file mode 100644
index 0000000..b0e8399
--- /dev/null
+++ b/specs/fenestra/examples/0.1.0/stripe.fenestra.yaml
@@ -0,0 +1,1033 @@
+# Fenestra Document: Stripe Elements
+#
+# Stripe Elements represents an embeddedSdk extension type - pre-built UI components
+# that developers embed in their websites for secure payment collection.
+#
+# Key characteristics:
+# - SDK MUST be loaded from Stripe's CDN (cannot be bundled)
+# - Handles PCI compliance automatically
+# - Extensive customization via Appearance API
+# - Components integrate seamlessly into merchant checkout pages
+
+fenestra: "0.1.0"
+
+info:
+ title: Stripe Elements UI Ecosystem
+ version: "1.0.0"
+ description: |
+ Stripe Elements is a set of pre-built UI components for securely collecting
+ payment information on the web. Elements are designed to be embedded in
+ merchant checkout pages and handle the complex requirements of payment security.
+
+ Stripe.js and Elements provide:
+ - PCI DSS Level 1 compliant payment collection
+ - Automatic card validation and formatting
+ - Support for 40+ payment methods
+ - Dynamic localization for 40+ languages
+ - Real-time error handling and validation
+ - Extensive styling and theming capabilities
+
+ Security Model: Payment data never touches merchant servers. Elements communicate
+ directly with Stripe, significantly reducing PCI compliance scope.
+
+platform:
+ name: Stripe
+ vendor: Stripe, Inc.
+ documentation: https://stripe.com/docs
+ appMarketplace: https://marketplace.stripe.com/
+
+# =============================================================================
+# SDK DEFINITIONS
+# =============================================================================
+
+sdks:
+ stripe-js:
+ name: Stripe.js
+ packageManager: npm
+ package: "@stripe/stripe-js"
+ version: "^2.0.0"
+ platform: web
+ documentation: https://stripe.com/docs/js
+ repository: https://github.com/stripe/stripe-js
+ cdn: https://js.stripe.com/v3/
+ cdnRequired: true
+ installCommand: npm install @stripe/stripe-js
+ exports:
+ loadStripe:
+ type: utility
+ description: Loads Stripe.js asynchronously from CDN
+ Stripe:
+ type: utility
+ description: Main Stripe.js instance for creating Elements
+
+ react-stripe-js:
+ name: React Stripe.js
+ packageManager: npm
+ package: "@stripe/react-stripe-js"
+ version: "^2.0.0"
+ platform: web
+ documentation: https://stripe.com/docs/stripe-js/react
+ repository: https://github.com/stripe/react-stripe-js
+ installCommand: npm install @stripe/react-stripe-js @stripe/stripe-js
+ exports:
+ # Provider Components
+ Elements:
+ type: component
+ description: Provider component that wraps all Stripe Elements
+ # Element Components
+ PaymentElement:
+ type: component
+ description: All-in-one payment method collection component
+ CardElement:
+ type: component
+ description: Complete card input (number, expiry, CVC)
+ CardNumberElement:
+ type: component
+ description: Card number input only
+ CardExpiryElement:
+ type: component
+ description: Card expiry date input only
+ CardCvcElement:
+ type: component
+ description: Card CVC input only
+ ExpressCheckoutElement:
+ type: component
+ description: One-click payment buttons (Apple Pay, Google Pay, etc.)
+ LinkAuthenticationElement:
+ type: component
+ description: Email input with Link autofill
+ AddressElement:
+ type: component
+ description: Complete address collection form
+ PaymentMethodMessagingElement:
+ type: component
+ description: Marketing messages for payment methods (BNPL, etc.)
+ IbanElement:
+ type: component
+ description: IBAN input for SEPA Direct Debit
+ IdealBankElement:
+ type: component
+ description: iDEAL bank selection
+ AuBankAccountElement:
+ type: component
+ description: Australian bank account input
+ # Hooks
+ useStripe:
+ type: hook
+ description: Hook to access Stripe instance
+ useElements:
+ type: hook
+ description: Hook to access Elements instance
+
+ stripe-ios:
+ name: Stripe iOS SDK
+ packageManager: cocoapods
+ package: Stripe
+ version: "^23.0.0"
+ platform: ios
+ documentation: https://stripe.com/docs/mobile/ios
+ repository: https://github.com/stripe/stripe-ios
+ installCommand: pod 'Stripe'
+ mobile:
+ minOsVersion: "13.0"
+ targetOsVersion: "17.0"
+ architectures: [arm64, x86_64]
+ appStoreGuidelines: https://stripe.com/docs/security/guide#app-store
+
+ stripe-android:
+ name: Stripe Android SDK
+ packageManager: gradle
+ package: com.stripe:stripe-android
+ version: "^20.0.0"
+ platform: android
+ documentation: https://stripe.com/docs/mobile/android
+ repository: https://github.com/stripe/stripe-android
+ installCommand: implementation 'com.stripe:stripe-android:20.+'
+ mobile:
+ minOsVersion: "5.0"
+ targetOsVersion: "14.0"
+
+ stripe-react-native:
+ name: Stripe React Native SDK
+ packageManager: npm
+ package: "@stripe/stripe-react-native"
+ version: "^0.35.0"
+ platform: react-native
+ documentation: https://stripe.com/docs/mobile/react-native
+ repository: https://github.com/stripe/stripe-react-native
+ installCommand: npm install @stripe/stripe-react-native
+
+# =============================================================================
+# COMPONENT CATALOG
+# =============================================================================
+
+componentCatalog:
+ categories:
+ payment:
+ name: Payment Collection
+ description: Components for collecting payment information
+ components:
+ - PaymentElement
+ - CardElement
+ - CardNumberElement
+ - CardExpiryElement
+ - CardCvcElement
+ - IbanElement
+ - IdealBankElement
+ - AuBankAccountElement
+
+ express:
+ name: Express Checkout
+ description: One-click payment experiences
+ components:
+ - ExpressCheckoutElement
+
+ identity:
+ name: Identity & Authentication
+ description: User identification and Link integration
+ components:
+ - LinkAuthenticationElement
+
+ address:
+ name: Address Collection
+ description: Shipping and billing address forms
+ components:
+ - AddressElement
+
+ messaging:
+ name: Payment Messaging
+ description: Marketing and informational messages
+ components:
+ - PaymentMethodMessagingElement
+
+ components:
+ PaymentElement:
+ name: Payment Element
+ description: |
+ All-in-one component that dynamically displays relevant payment methods
+ based on transaction amount, currency, and customer location. Recommended
+ for most integrations as it automatically adapts to customer preferences.
+ category: payment
+ sdkBinding:
+ sdk: react-stripe-js
+ export: PaymentElement
+ importPath: "@stripe/react-stripe-js"
+ webStandardMapping:
+ htmlElement: div
+ ariaRole: group
+ semanticType: input
+ props:
+ type: object
+ properties:
+ options:
+ type: object
+ properties:
+ layout:
+ type: string
+ enum: [tabs, accordion, auto]
+ default: auto
+ description: How to display multiple payment methods
+ business:
+ type: object
+ description: Business name shown to customers
+ fields:
+ type: object
+ properties:
+ billingDetails:
+ type: string
+ enum: [auto, never]
+ description: Whether to collect billing details
+ wallets:
+ type: object
+ properties:
+ applePay:
+ type: string
+ enum: [auto, never]
+ googlePay:
+ type: string
+ enum: [auto, never]
+ readOnly:
+ type: boolean
+ default: false
+ onChange:
+ type: function
+ description: Callback when payment method state changes
+ onReady:
+ type: function
+ description: Callback when component is fully loaded
+ onFocus:
+ type: function
+ onBlur:
+ type: function
+ events:
+ change:
+ description: Payment method or validation state changed
+ payload:
+ type: object
+ properties:
+ complete:
+ type: boolean
+ value:
+ type: object
+ ready:
+ description: Component fully loaded and ready
+ focus:
+ description: Component received focus
+ blur:
+ description: Component lost focus
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ focusManagement: Automatic focus management within multi-field component
+ notes: |
+ Stripe Elements are built with accessibility in mind, including
+ proper ARIA labels, keyboard navigation, and screen reader support.
+ examples:
+ - title: Basic Payment Element
+ code: |
+ import { PaymentElement } from '@stripe/react-stripe-js';
+
+ function CheckoutForm() {
+ return (
+
+ );
+ }
+ language: jsx
+ - title: Payment Element with Options
+ code: |
+ {
+ if (event.complete) {
+ console.log('Payment method ready');
+ }
+ }}
+ />
+ language: jsx
+
+ CardElement:
+ name: Card Element
+ description: |
+ Single-line card input that collects card number, expiry date, and CVC.
+ Provides automatic formatting, validation, and card brand detection.
+ category: payment
+ sdkBinding:
+ sdk: react-stripe-js
+ export: CardElement
+ importPath: "@stripe/react-stripe-js"
+ webStandardMapping:
+ htmlElement: div
+ ariaRole: group
+ semanticType: input
+ props:
+ type: object
+ properties:
+ options:
+ type: object
+ properties:
+ hidePostalCode:
+ type: boolean
+ default: false
+ iconStyle:
+ type: string
+ enum: [solid, default]
+ disabled:
+ type: boolean
+ default: false
+ onChange:
+ type: function
+ onReady:
+ type: function
+ onFocus:
+ type: function
+ onBlur:
+ type: function
+ events:
+ change:
+ description: Card input state changed
+ payload:
+ type: object
+ properties:
+ complete:
+ type: boolean
+ brand:
+ type: string
+ description: "Card brand: visa, mastercard, amex, etc."
+ error:
+ type: object
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ focusManagement: Single tab stop with internal field navigation
+ examples:
+ - title: Basic Card Element
+ code: |
+ import { CardElement } from '@stripe/react-stripe-js';
+
+ {
+ console.log('Brand:', event.brand);
+ if (event.error) {
+ console.error(event.error.message);
+ }
+ }}
+ />
+ language: jsx
+
+ ExpressCheckoutElement:
+ name: Express Checkout Element
+ description: |
+ Displays one-click payment buttons (Apple Pay, Google Pay, Link, etc.)
+ based on customer device and saved payment methods. Automatically handles
+ eligibility and payment sheet presentation.
+ category: express
+ sdkBinding:
+ sdk: react-stripe-js
+ export: ExpressCheckoutElement
+ importPath: "@stripe/react-stripe-js"
+ webStandardMapping:
+ htmlElement: div
+ ariaRole: button
+ semanticType: action
+ props:
+ type: object
+ properties:
+ options:
+ type: object
+ properties:
+ buttonType:
+ type: object
+ properties:
+ applePay:
+ type: string
+ enum: [plain, buy, donate, check-out, book, subscribe]
+ googlePay:
+ type: string
+ enum: [buy, donate, plain, book, checkout, subscribe, pay]
+ buttonTheme:
+ type: object
+ properties:
+ applePay:
+ type: string
+ enum: [black, white, white-outline]
+ googlePay:
+ type: string
+ enum: [black, white]
+ buttonHeight:
+ type: string
+ description: CSS height value (e.g., "48px")
+ onConfirm:
+ type: function
+ description: Called when customer authorizes payment
+ onClick:
+ type: function
+ description: Called when button is clicked
+ examples:
+ - title: Express Checkout Element
+ code: |
+ import { ExpressCheckoutElement } from '@stripe/react-stripe-js';
+
+ {
+ // Handle payment confirmation
+ const { error } = await stripe.confirmPayment({
+ elements,
+ confirmParams: { return_url: '...' }
+ });
+ }}
+ />
+ language: jsx
+
+ LinkAuthenticationElement:
+ name: Link Authentication Element
+ description: |
+ Email input with Link integration. Allows returning customers to
+ autofill their payment details with a simple OTP verification.
+ category: identity
+ sdkBinding:
+ sdk: react-stripe-js
+ export: LinkAuthenticationElement
+ importPath: "@stripe/react-stripe-js"
+ webStandardMapping:
+ htmlElement: input
+ ariaRole: textbox
+ semanticType: input
+ props:
+ type: object
+ properties:
+ options:
+ type: object
+ properties:
+ defaultValues:
+ type: object
+ properties:
+ email:
+ type: string
+ onChange:
+ type: function
+ examples:
+ - title: Link Authentication Element
+ code: |
+ import { LinkAuthenticationElement } from '@stripe/react-stripe-js';
+
+ {
+ console.log('Email:', event.value.email);
+ }}
+ />
+ language: jsx
+
+ AddressElement:
+ name: Address Element
+ description: |
+ Complete address collection form with automatic postal code lookup,
+ address validation, and international format support. Adapts fields
+ based on selected country.
+ category: address
+ sdkBinding:
+ sdk: react-stripe-js
+ export: AddressElement
+ importPath: "@stripe/react-stripe-js"
+ webStandardMapping:
+ htmlElement: div
+ ariaRole: group
+ semanticType: input
+ props:
+ type: object
+ properties:
+ options:
+ type: object
+ properties:
+ mode:
+ type: string
+ enum: [shipping, billing]
+ description: Determines required fields
+ allowedCountries:
+ type: array
+ items:
+ type: string
+ description: ISO country codes
+ autocomplete:
+ type: object
+ properties:
+ mode:
+ type: string
+ enum: [automatic, google_maps_api, disabled]
+ defaultValues:
+ type: object
+ properties:
+ name:
+ type: string
+ address:
+ type: object
+ fields:
+ type: object
+ properties:
+ phone:
+ type: string
+ enum: [always, auto, never]
+ onChange:
+ type: function
+ examples:
+ - title: Shipping Address Element
+ code: |
+ import { AddressElement } from '@stripe/react-stripe-js';
+
+ {
+ if (event.complete) {
+ console.log('Address:', event.value.address);
+ }
+ }}
+ />
+ language: jsx
+
+ PaymentMethodMessagingElement:
+ name: Payment Method Messaging Element
+ description: |
+ Displays promotional messaging for payment methods like "Pay in 4
+ interest-free installments" for Buy Now, Pay Later options.
+ category: messaging
+ sdkBinding:
+ sdk: react-stripe-js
+ export: PaymentMethodMessagingElement
+ importPath: "@stripe/react-stripe-js"
+ webStandardMapping:
+ htmlElement: div
+ ariaRole: region
+ semanticType: display
+ props:
+ type: object
+ properties:
+ options:
+ type: object
+ properties:
+ amount:
+ type: number
+ description: Amount in cents
+ currency:
+ type: string
+ paymentMethodTypes:
+ type: array
+ items:
+ type: string
+ countryCode:
+ type: string
+ examples:
+ - title: Afterpay Messaging
+ code: |
+ import { PaymentMethodMessagingElement } from '@stripe/react-stripe-js';
+
+
+ language: jsx
+
+ IbanElement:
+ name: IBAN Element
+ description: |
+ IBAN input for SEPA Direct Debit payments. Automatically validates
+ IBAN format and displays supported country codes.
+ category: payment
+ sdkBinding:
+ sdk: react-stripe-js
+ export: IbanElement
+ importPath: "@stripe/react-stripe-js"
+ webStandardMapping:
+ htmlElement: input
+ ariaRole: textbox
+ semanticType: input
+ props:
+ type: object
+ properties:
+ options:
+ type: object
+ properties:
+ supportedCountries:
+ type: array
+ items:
+ type: string
+ placeholderCountry:
+ type: string
+ examples:
+ - title: SEPA Direct Debit
+ code: |
+ import { IbanElement } from '@stripe/react-stripe-js';
+
+
+ language: jsx
+
+# =============================================================================
+# EXTENSION POINTS
+# =============================================================================
+
+extensionPoints:
+ - id: merchant-checkout-page
+ name: Merchant Checkout Page
+ type: embedded
+ extensionType: embeddedSdk
+ description: |
+ Stripe Elements are embedded directly into merchant checkout pages.
+ The SDK creates secure iframe-based inputs that merchants style and
+ position within their own page layout. Payment data flows directly
+ from the customer's browser to Stripe without touching merchant servers.
+
+ extensionTypeConfig:
+ sdk:
+ package: "@stripe/stripe-js"
+ cdn: https://js.stripe.com/v3/
+ cdnRequired: true
+
+ mountPattern: domSelector
+
+ theming:
+ system: Appearance API
+ customizable: true
+ variables:
+ - theme
+ - variables.colorPrimary
+ - variables.colorBackground
+ - variables.colorText
+ - variables.colorDanger
+ - variables.fontFamily
+ - variables.spacingUnit
+ - variables.borderRadius
+ - variables.fontSizeBase
+ - variables.fontSizeSm
+ - variables.fontSizeXs
+ - rules (CSS-like object)
+ prebuiltThemes:
+ - stripe
+ - night
+ - flat
+ - none
+
+ communication:
+ pattern: promises
+ events:
+ - ready
+ - change
+ - focus
+ - blur
+ - escape
+ - networkerror
+
+ supportedComponents:
+ - PaymentElement
+ - CardElement
+ - CardNumberElement
+ - CardExpiryElement
+ - CardCvcElement
+ - ExpressCheckoutElement
+ - LinkAuthenticationElement
+ - AddressElement
+ - PaymentMethodMessagingElement
+ - IbanElement
+ - IdealBankElement
+ - AuBankAccountElement
+
+ constraints:
+ responsive: true
+
+ context:
+ provides:
+ - publishableKey
+ - clientSecret
+ - customer
+ - locale
+ actions:
+ - createPaymentMethod
+ - confirmPayment
+ - confirmSetup
+ - handleCardAction
+ - retrievePaymentIntent
+ - retrieveSetupIntent
+
+ - id: mobile-checkout
+ name: Mobile Native Checkout
+ type: embedded
+ extensionType: embeddedSdk
+ description: |
+ Native mobile SDKs for iOS and Android provide pre-built UI components
+ for payment collection with platform-native look and feel.
+
+ extensionTypeConfig:
+ sdk:
+ package: Stripe
+ cdnRequired: false
+
+ mountPattern: function
+
+ theming:
+ system: Platform Native
+ customizable: true
+ variables:
+ - primaryBackgroundColor
+ - secondaryBackgroundColor
+ - primaryForegroundColor
+ - secondaryForegroundColor
+ - accentColor
+ - errorColor
+ - font
+
+ communication:
+ pattern: callbacks
+ events:
+ - didChange
+ - didFinish
+ - didFail
+
+ supportedComponents:
+ - PaymentSheet
+ - CardForm
+ - ApplePayButton
+ - GooglePayButton
+
+ context:
+ provides:
+ - publishableKey
+ - ephemeralKey
+ - customer
+ - paymentIntent
+ actions:
+ - presentPaymentSheet
+ - confirmPayment
+ - createPaymentMethod
+
+# =============================================================================
+# POLICIES
+# =============================================================================
+
+policies:
+ componentRequirement:
+ level: required
+ scope: all
+ rationale: |
+ Stripe Elements components MUST be used for payment data collection
+ to maintain PCI DSS Level 1 compliance. Payment data never touches
+ merchant servers - it flows directly from Elements to Stripe.
+
+ This requirement is non-negotiable for security and compliance reasons.
+
+ customComponents:
+ allowed: false
+ constraints:
+ - Merchants cannot create custom payment input fields
+ - All payment data collection must use Stripe Elements
+ - Styling is allowed via Appearance API only
+ documentation: https://stripe.com/docs/security/guide
+
+ publishing:
+ allIntegrations:
+ componentRequirement: required
+ customComponentsAllowed: false
+ reviewRequired: false
+ notes: |
+ All Stripe integrations, whether using publishable or restricted keys,
+ must use Elements for payment collection. No exceptions.
+
+ designGuidelines:
+ required: false
+ designSystem: "Appearance API"
+ designSystemUrl: https://stripe.com/docs/elements/appearance-api
+ designTokensProvided: true
+
+ security:
+ cdnRequirement:
+ required: true
+ rationale: |
+ Stripe.js MUST be loaded from js.stripe.com CDN. Self-hosting or
+ bundling Stripe.js is prohibited for security reasons:
+
+ 1. Stripe can push critical security updates instantly
+ 2. Version integrity is guaranteed
+ 3. PCI compliance is maintained
+ 4. TLS and certificate management is handled by Stripe
+ enforcement: Runtime validation
+ documentation: https://stripe.com/docs/security/guide#validating-pci-compliance
+
+ pciCompliance:
+ level: PCI DSS Level 1
+ scope: Stripe handles all payment data
+ merchantScope: SAQ A (minimal compliance burden)
+ documentation: https://stripe.com/docs/security
+
+# =============================================================================
+# RENDERING ENGINES
+# =============================================================================
+
+renderingEngines:
+ stripe-elements:
+ type: custom
+ name: Stripe Elements Renderer
+ description: |
+ Secure iframe-based rendering engine. Each Element component creates
+ an isolated iframe that communicates with the parent page via postMessage.
+ This ensures payment data never touches the merchant's JavaScript context.
+
+ sandboxing:
+ iframeSandbox: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ cspPolicy: |
+ Merchants must allow https://js.stripe.com in their CSP:
+ script-src https://js.stripe.com;
+ frame-src https://js.stripe.com;
+ connect-src https://api.stripe.com;
+
+ react-renderer:
+ type: react
+ name: React Stripe.js
+ description: |
+ React wrapper components that manage Element lifecycle and provide
+ idiomatic React patterns (hooks, context, etc.) while maintaining
+ the same security model as vanilla Stripe.js.
+
+# =============================================================================
+# EXTENSIONS
+# =============================================================================
+
+x-compliance:
+ security:
+ platformCertifications:
+ - PCI DSS Level 1
+ - SOC 2 Type II
+ - ISO 27001
+ extensionRequirements:
+ httpsOnly: true
+ cspCompliance: true
+ noInlineScripts: true
+ noExternalScripts: false
+ securityReview:
+ required: false
+ scope: none
+ dataHandling:
+ piiAllowed: true
+ piiMustEncrypt: true
+ dataRetentionPolicy: none
+ documentation: https://stripe.com/docs/security
+
+ privacy:
+ platformCompliance:
+ gdpr: true
+ ccpa: true
+ dataResidency:
+ available: true
+ regions:
+ - US
+ - EU
+ - APAC
+ extensionRequirements:
+ privacyPolicyRequired: true
+ consentManagement: both
+ dataProcessingAgreement: required
+ userRights:
+ dataExportSupported: true
+ dataDeletionSupported: true
+ documentation: https://stripe.com/privacy
+
+ sharedResponsibility:
+ platformHandles:
+ - Payment data collection and storage
+ - PCI DSS compliance
+ - Card tokenization
+ - Payment processing security
+ - Fraud detection (Stripe Radar)
+ - Strong Customer Authentication (SCA/3DS)
+ - Regional payment method support
+ developerHandles:
+ - HTTPS implementation on their domain
+ - User authentication and authorization
+ - Order/transaction data storage
+ - Privacy policy and terms of service
+ - User consent management
+ - Webhook signature verification
+ documentation: https://stripe.com/docs/security/guide
+
+x-i18n:
+ platformSupport:
+ enabled: true
+ availableLocales:
+ - ar # Arabic
+ - bg # Bulgarian
+ - cs # Czech
+ - da # Danish
+ - de # German
+ - el # Greek
+ - en # English
+ - en-GB # English (UK)
+ - es # Spanish
+ - es-419 # Spanish (Latin America)
+ - et # Estonian
+ - fi # Finnish
+ - fil # Filipino
+ - fr # French
+ - fr-CA # French (Canada)
+ - he # Hebrew
+ - hr # Croatian
+ - hu # Hungarian
+ - id # Indonesian
+ - it # Italian
+ - ja # Japanese
+ - ko # Korean
+ - lt # Lithuanian
+ - lv # Latvian
+ - ms # Malay
+ - mt # Maltese
+ - nb # Norwegian Bokmål
+ - nl # Dutch
+ - pl # Polish
+ - pt # Portuguese (Brazil)
+ - pt-BR # Portuguese (Brazil)
+ - ro # Romanian
+ - ru # Russian
+ - sk # Slovak
+ - sl # Slovenian
+ - sv # Swedish
+ - th # Thai
+ - tr # Turkish
+ - vi # Vietnamese
+ - zh # Chinese (Simplified)
+ - zh-HK # Chinese (Hong Kong)
+ - zh-TW # Chinese (Traditional)
+ localeDetection:
+ method: automatic
+ sources:
+ - stripe.elements({ locale: '...' }) option
+ - Accept-Language header
+ - Customer's saved preferences
+ rtlSupport:
+ enabled: true
+ languages:
+ - ar # Arabic
+ - he # Hebrew
+
+ componentTranslations:
+ provided: true
+ scope: all
+
+ developerRequirements:
+ translationMechanism:
+ format: json
+ bundleLocation: platform-hosted
+ marketplaceRequirement:
+ required: false
+ formatting:
+ dates: platform
+ numbers: platform
+ currencies: platform
+
+ documentation: https://stripe.com/docs/js/appendix/supported_locales
diff --git a/specs/fenestra/examples/0.1.0/teams.fenestra.yaml b/specs/fenestra/examples/0.1.0/teams.fenestra.yaml
new file mode 100644
index 0000000..33920eb
--- /dev/null
+++ b/specs/fenestra/examples/0.1.0/teams.fenestra.yaml
@@ -0,0 +1,1844 @@
+# Fenestra Document: Microsoft Teams Platform
+#
+# Microsoft Teams represents a hybrid extensibility model combining:
+# 1. Adaptive Cards - Declarative JSON-based UI (like Slack Block Kit)
+# 2. Tabs - Embedded web apps in sandboxed iframes
+# 3. Bots - Conversational interfaces with Adaptive Card responses
+# 4. Message Extensions - Search and action commands
+# 5. Meeting Extensions - In-meeting experiences
+#
+# This specification documents both patterns: declarative (Adaptive Cards)
+# and iframe-based (Tabs), plus the Teams JavaScript SDK for context and interaction.
+
+fenestra: "0.1.0"
+
+info:
+ title: Microsoft Teams App Platform
+ version: "1.24.0"
+ description: |
+ Microsoft Teams App Platform enables developers to build collaborative
+ experiences using a hybrid model of declarative UI and embedded web content.
+
+ Key characteristics:
+ - Adaptive Cards: JSON-based declarative UI for bots and messages (REQUIRED)
+ - Tabs: Full web apps embedded in iframes with Teams context
+ - Bots: Conversational AI using Bot Framework + Adaptive Cards
+ - Message Extensions: Search/action commands extending compose box
+ - Meeting Extensions: In-meeting apps, stages, and panels
+ - Teams JS SDK: Bridge between iframe tabs and Teams context
+
+ Teams apps work across Microsoft Teams, Outlook, and Microsoft 365 app.
+
+ contact:
+ name: Microsoft Teams Platform Team
+ url: https://learn.microsoft.com/en-us/microsoftteams/platform/feedback
+ email: microsoftteamsdev@microsoft.com
+
+platform:
+ name: Microsoft Teams
+ vendor: Microsoft Corporation
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/
+ appMarketplace: https://appsource.microsoft.com/en-us/marketplace/apps?product=teams
+ developerPortal: https://dev.teams.microsoft.com/
+ changelog: https://learn.microsoft.com/en-us/microsoftteams/platform/whats-new
+
+sdks:
+ teams-js:
+ name: Microsoft Teams JavaScript SDK
+ packageManager: npm
+ package: "@microsoft/teams-js"
+ version: "^2.47.2"
+ repository: https://github.com/OfficeDev/microsoft-teams-library-js
+ documentation: https://learn.microsoft.com/en-us/javascript/api/overview/msteams-client
+ description: |
+ The TeamsJS library enables tabs (web pages) to access Teams context,
+ authenticate users, open dialogs, and interact with Teams capabilities.
+ Starting with v2.0, TeamsJS enables apps to run in Teams, Outlook, and
+ Microsoft 365 app.
+ exports:
+ app:
+ type: namespace
+ description: Core app initialization and context
+ authentication:
+ type: namespace
+ description: Authentication flows and token management
+ dialog:
+ type: namespace
+ description: Open dialogs and task modules
+ pages:
+ type: namespace
+ description: Page navigation and configuration
+ meeting:
+ type: namespace
+ description: Meeting-specific capabilities
+ chat:
+ type: namespace
+ description: Chat and channel interactions
+ calendar:
+ type: namespace
+ description: Calendar integration
+
+ adaptivecards:
+ name: Adaptive Cards SDK
+ packageManager: npm
+ package: "adaptivecards"
+ version: "^3.0.4"
+ repository: https://github.com/microsoft/AdaptiveCards
+ documentation: https://learn.microsoft.com/en-us/adaptive-cards/sdk/rendering-cards/javascript/getting-started
+ description: |
+ JavaScript SDK for rendering Adaptive Cards. Used primarily for
+ previewing cards during development. In production, Teams/Outlook
+ render Adaptive Cards natively.
+ exports:
+ AdaptiveCard:
+ type: class
+ description: Adaptive Card renderer
+ HostConfig:
+ type: class
+ description: Host configuration for styling cards
+ Version:
+ type: utility
+ description: Schema version utilities
+
+ botbuilder:
+ name: Microsoft Bot Framework SDK
+ packageManager: npm
+ package: "botbuilder"
+ version: "^4.22.3"
+ repository: https://github.com/microsoft/botbuilder-js
+ documentation: https://learn.microsoft.com/en-us/azure/bot-service/
+ description: |
+ Bot Framework SDK for building conversational bots. Teams bots use
+ this SDK to handle messages, send Adaptive Cards, and respond to
+ user interactions.
+ exports:
+ BotFrameworkAdapter:
+ type: class
+ description: Adapter for Bot Framework protocol
+ TeamsActivityHandler:
+ type: class
+ description: Teams-specific bot handler
+ CardFactory:
+ type: utility
+ description: Factory for creating Adaptive Cards and other card types
+ MessageFactory:
+ type: utility
+ description: Factory for creating bot messages
+
+componentCatalog:
+ categories:
+ cardElements:
+ name: Adaptive Card Elements
+ description: Visual elements for displaying content in cards
+ components:
+ - TextBlock
+ - Image
+ - Media
+ - RichTextBlock
+ - Table
+ - FactSet
+ - ImageSet
+
+ cardContainers:
+ name: Adaptive Card Containers
+ description: Layout containers for organizing card content
+ components:
+ - Container
+ - ColumnSet
+ - Column
+ - ActionSet
+
+ cardInputs:
+ name: Adaptive Card Inputs
+ description: Form inputs for collecting user data
+ components:
+ - InputText
+ - InputNumber
+ - InputDate
+ - InputTime
+ - InputToggle
+ - InputChoiceSet
+
+ cardActions:
+ name: Adaptive Card Actions
+ description: Interactive actions users can trigger
+ components:
+ - ActionSubmit
+ - ActionOpenUrl
+ - ActionShowCard
+ - ActionToggleVisibility
+ - ActionExecute
+
+ components:
+ # ADAPTIVE CARD ELEMENTS
+
+ TextBlock:
+ name: TextBlock
+ description: Display text with formatting options
+ category: cardElements
+ sdkBinding:
+ type: jsonSchema
+ elementType: TextBlock
+ webStandardMapping:
+ htmlElement: p
+ ariaRole: text
+ semanticType: display
+ schema:
+ type: object
+ required: [type, text]
+ properties:
+ type:
+ type: string
+ const: TextBlock
+ text:
+ type: string
+ description: Text content (supports Markdown subset)
+ color:
+ type: string
+ enum: [default, dark, light, accent, good, warning, attention]
+ fontType:
+ type: string
+ enum: [default, monospace]
+ size:
+ type: string
+ enum: [small, default, medium, large, extraLarge]
+ weight:
+ type: string
+ enum: [lighter, default, bolder]
+ isSubtle:
+ type: boolean
+ maxLines:
+ type: integer
+ description: Maximum lines before truncation
+ wrap:
+ type: boolean
+ description: Enable text wrapping
+ horizontalAlignment:
+ type: string
+ enum: [left, center, right]
+ id:
+ type: string
+ description: Unique element identifier
+ constraints:
+ supportsMarkdown: true
+ markdownSubset: basic
+ accessibility:
+ screenReaderSupport: true
+
+ Image:
+ name: Image
+ description: Display an image
+ category: cardElements
+ sdkBinding:
+ type: jsonSchema
+ elementType: Image
+ webStandardMapping:
+ htmlElement: img
+ ariaRole: img
+ semanticType: media
+ schema:
+ type: object
+ required: [type, url]
+ properties:
+ type:
+ type: string
+ const: Image
+ url:
+ type: string
+ format: uri
+ description: Image URL (https required)
+ altText:
+ type: string
+ description: Alternative text for accessibility
+ backgroundColor:
+ type: string
+ description: Background color (hex)
+ size:
+ type: string
+ enum: [auto, stretch, small, medium, large]
+ style:
+ type: string
+ enum: [default, person]
+ description: "person = circular crop for profile pictures"
+ width:
+ type: string
+ description: Explicit width (e.g., "50px")
+ height:
+ type: string
+ description: Explicit height (e.g., "50px")
+ horizontalAlignment:
+ type: string
+ enum: [left, center, right]
+ selectAction:
+ description: Action when image is clicked
+ oneOf:
+ - $ref: "#/components/ActionOpenUrl"
+ - $ref: "#/components/ActionSubmit"
+ id:
+ type: string
+ accessibility:
+ altTextRequired: true
+ screenReaderSupport: true
+
+ Media:
+ name: Media
+ description: Display audio or video content
+ category: cardElements
+ sdkBinding:
+ type: jsonSchema
+ elementType: Media
+ webStandardMapping:
+ htmlElement: video
+ semanticType: media
+ schema:
+ type: object
+ required: [type, sources]
+ properties:
+ type:
+ type: string
+ const: Media
+ sources:
+ type: array
+ items:
+ type: object
+ required: [mimeType, url]
+ properties:
+ mimeType:
+ type: string
+ description: "video/mp4, audio/mp3, etc."
+ url:
+ type: string
+ format: uri
+ poster:
+ type: string
+ format: uri
+ description: Thumbnail image URL
+ altText:
+ type: string
+ id:
+ type: string
+
+ RichTextBlock:
+ name: RichTextBlock
+ description: Display rich formatted text with inline elements
+ category: cardElements
+ sdkBinding:
+ type: jsonSchema
+ elementType: RichTextBlock
+ schema:
+ type: object
+ required: [type, inlines]
+ properties:
+ type:
+ type: string
+ const: RichTextBlock
+ inlines:
+ type: array
+ description: Array of TextRun objects
+ items:
+ type: object
+ properties:
+ type:
+ const: TextRun
+ text:
+ type: string
+ color:
+ type: string
+ fontType:
+ type: string
+ highlight:
+ type: boolean
+ isSubtle:
+ type: boolean
+ italic:
+ type: boolean
+ selectAction:
+ type: object
+ size:
+ type: string
+ strikethrough:
+ type: boolean
+ underline:
+ type: boolean
+ weight:
+ type: string
+ horizontalAlignment:
+ type: string
+ enum: [left, center, right]
+ id:
+ type: string
+
+ Table:
+ name: Table
+ description: Display tabular data (Adaptive Cards v1.5+)
+ category: cardElements
+ sdkBinding:
+ type: jsonSchema
+ elementType: Table
+ webStandardMapping:
+ htmlElement: table
+ semanticType: display
+ schema:
+ type: object
+ required: [type, columns, rows]
+ properties:
+ type:
+ type: string
+ const: Table
+ columns:
+ type: array
+ items:
+ type: object
+ properties:
+ width:
+ type: string
+ verticalCellContentAlignment:
+ type: string
+ horizontalCellContentAlignment:
+ type: string
+ rows:
+ type: array
+ items:
+ type: object
+ required: [type, cells]
+ properties:
+ type:
+ const: TableRow
+ cells:
+ type: array
+ items:
+ type: object
+ properties:
+ type:
+ const: TableCell
+ items:
+ type: array
+ showGridLines:
+ type: boolean
+ gridStyle:
+ type: string
+ enum: [default, emphasis, accent]
+ id:
+ type: string
+
+ FactSet:
+ name: FactSet
+ description: Display key-value pairs as facts
+ category: cardElements
+ sdkBinding:
+ type: jsonSchema
+ elementType: FactSet
+ webStandardMapping:
+ htmlElement: dl
+ semanticType: display
+ schema:
+ type: object
+ required: [type, facts]
+ properties:
+ type:
+ type: string
+ const: FactSet
+ facts:
+ type: array
+ items:
+ type: object
+ required: [title, value]
+ properties:
+ title:
+ type: string
+ description: Fact label
+ value:
+ type: string
+ description: Fact value
+ id:
+ type: string
+
+ ImageSet:
+ name: ImageSet
+ description: Display a gallery of images
+ category: cardElements
+ sdkBinding:
+ type: jsonSchema
+ elementType: ImageSet
+ schema:
+ type: object
+ required: [type, images]
+ properties:
+ type:
+ type: string
+ const: ImageSet
+ images:
+ type: array
+ items:
+ $ref: "#/components/Image"
+ imageSize:
+ type: string
+ enum: [auto, stretch, small, medium, large]
+ id:
+ type: string
+
+ # CONTAINERS
+
+ Container:
+ name: Container
+ description: Groups elements together with styling
+ category: cardContainers
+ sdkBinding:
+ type: jsonSchema
+ elementType: Container
+ webStandardMapping:
+ htmlElement: div
+ ariaRole: region
+ semanticType: container
+ schema:
+ type: object
+ required: [type, items]
+ properties:
+ type:
+ type: string
+ const: Container
+ items:
+ type: array
+ description: Array of card elements
+ style:
+ type: string
+ enum: [default, emphasis, good, attention, warning, accent]
+ verticalContentAlignment:
+ type: string
+ enum: [top, center, bottom]
+ bleed:
+ type: boolean
+ description: Bleed to parent container edges
+ backgroundImage:
+ type: string
+ format: uri
+ minHeight:
+ type: string
+ selectAction:
+ type: object
+ id:
+ type: string
+
+ ColumnSet:
+ name: ColumnSet
+ description: Arrange elements in columns
+ category: cardContainers
+ sdkBinding:
+ type: jsonSchema
+ elementType: ColumnSet
+ webStandardMapping:
+ htmlElement: div
+ semanticType: layout
+ schema:
+ type: object
+ required: [type, columns]
+ properties:
+ type:
+ type: string
+ const: ColumnSet
+ columns:
+ type: array
+ items:
+ $ref: "#/components/Column"
+ selectAction:
+ type: object
+ style:
+ type: string
+ bleed:
+ type: boolean
+ minHeight:
+ type: string
+ horizontalAlignment:
+ type: string
+ id:
+ type: string
+
+ Column:
+ name: Column
+ description: Single column within a ColumnSet
+ category: cardContainers
+ sdkBinding:
+ type: jsonSchema
+ elementType: Column
+ schema:
+ type: object
+ required: [type, items]
+ properties:
+ type:
+ type: string
+ const: Column
+ items:
+ type: array
+ description: Elements in this column
+ width:
+ description: "auto, stretch, weighted (1, 2, etc.), or pixel (50px)"
+ oneOf:
+ - type: string
+ - type: number
+ style:
+ type: string
+ verticalContentAlignment:
+ type: string
+ bleed:
+ type: boolean
+ backgroundImage:
+ type: string
+ selectAction:
+ type: object
+ id:
+ type: string
+
+ ActionSet:
+ name: ActionSet
+ description: Display a set of actions within card body
+ category: cardContainers
+ sdkBinding:
+ type: jsonSchema
+ elementType: ActionSet
+ webStandardMapping:
+ htmlElement: div
+ ariaRole: group
+ semanticType: container
+ schema:
+ type: object
+ required: [type, actions]
+ properties:
+ type:
+ type: string
+ const: ActionSet
+ actions:
+ type: array
+ description: Array of actions
+ items:
+ oneOf:
+ - $ref: "#/components/ActionSubmit"
+ - $ref: "#/components/ActionOpenUrl"
+ - $ref: "#/components/ActionShowCard"
+ - $ref: "#/components/ActionToggleVisibility"
+ id:
+ type: string
+
+ # INPUTS
+
+ InputText:
+ name: Input.Text
+ description: Single or multi-line text input
+ category: cardInputs
+ sdkBinding:
+ type: jsonSchema
+ elementType: Input.Text
+ webStandardMapping:
+ htmlElement: input
+ inputType: text
+ semanticType: input
+ schema:
+ type: object
+ required: [type, id]
+ properties:
+ type:
+ type: string
+ const: Input.Text
+ id:
+ type: string
+ description: Unique input identifier for form submission
+ placeholder:
+ type: string
+ value:
+ type: string
+ description: Default value
+ isMultiline:
+ type: boolean
+ maxLength:
+ type: integer
+ style:
+ type: string
+ enum: [text, tel, url, email, password]
+ inlineAction:
+ description: Action button shown inside input
+ oneOf:
+ - $ref: "#/components/ActionSubmit"
+ - $ref: "#/components/ActionExecute"
+ isRequired:
+ type: boolean
+ errorMessage:
+ type: string
+ label:
+ type: string
+ description: Accessible label (v1.3+)
+ accessibility:
+ labelRequired: true
+ screenReaderSupport: true
+
+ InputNumber:
+ name: Input.Number
+ description: Numeric input with validation
+ category: cardInputs
+ sdkBinding:
+ type: jsonSchema
+ elementType: Input.Number
+ webStandardMapping:
+ htmlElement: input
+ inputType: number
+ semanticType: input
+ schema:
+ type: object
+ required: [type, id]
+ properties:
+ type:
+ type: string
+ const: Input.Number
+ id:
+ type: string
+ placeholder:
+ type: string
+ value:
+ type: number
+ min:
+ type: number
+ max:
+ type: number
+ isRequired:
+ type: boolean
+ errorMessage:
+ type: string
+ label:
+ type: string
+
+ InputDate:
+ name: Input.Date
+ description: Date picker input
+ category: cardInputs
+ sdkBinding:
+ type: jsonSchema
+ elementType: Input.Date
+ webStandardMapping:
+ htmlElement: input
+ inputType: date
+ semanticType: input
+ schema:
+ type: object
+ required: [type, id]
+ properties:
+ type:
+ type: string
+ const: Input.Date
+ id:
+ type: string
+ value:
+ type: string
+ format: date
+ description: ISO 8601 date (YYYY-MM-DD)
+ placeholder:
+ type: string
+ min:
+ type: string
+ format: date
+ max:
+ type: string
+ format: date
+ isRequired:
+ type: boolean
+ errorMessage:
+ type: string
+ label:
+ type: string
+
+ InputTime:
+ name: Input.Time
+ description: Time picker input
+ category: cardInputs
+ sdkBinding:
+ type: jsonSchema
+ elementType: Input.Time
+ webStandardMapping:
+ htmlElement: input
+ inputType: time
+ semanticType: input
+ schema:
+ type: object
+ required: [type, id]
+ properties:
+ type:
+ type: string
+ const: Input.Time
+ id:
+ type: string
+ value:
+ type: string
+ description: "Time in HH:MM format (24-hour)"
+ placeholder:
+ type: string
+ min:
+ type: string
+ max:
+ type: string
+ isRequired:
+ type: boolean
+ errorMessage:
+ type: string
+ label:
+ type: string
+
+ InputToggle:
+ name: Input.Toggle
+ description: Checkbox or toggle switch
+ category: cardInputs
+ sdkBinding:
+ type: jsonSchema
+ elementType: Input.Toggle
+ webStandardMapping:
+ htmlElement: input
+ inputType: checkbox
+ ariaRole: switch
+ semanticType: input
+ schema:
+ type: object
+ required: [type, id, title]
+ properties:
+ type:
+ type: string
+ const: Input.Toggle
+ id:
+ type: string
+ title:
+ type: string
+ description: Label text next to toggle
+ value:
+ type: string
+ description: Value when toggled on (default "true")
+ valueOn:
+ type: string
+ default: "true"
+ valueOff:
+ type: string
+ default: "false"
+ wrap:
+ type: boolean
+ isRequired:
+ type: boolean
+ errorMessage:
+ type: string
+ label:
+ type: string
+
+ InputChoiceSet:
+ name: Input.ChoiceSet
+ description: Drop-down, radio buttons, or checkbox group
+ category: cardInputs
+ sdkBinding:
+ type: jsonSchema
+ elementType: Input.ChoiceSet
+ webStandardMapping:
+ htmlElement: select
+ ariaRole: listbox
+ semanticType: input
+ schema:
+ type: object
+ required: [type, id, choices]
+ properties:
+ type:
+ type: string
+ const: Input.ChoiceSet
+ id:
+ type: string
+ choices:
+ type: array
+ items:
+ type: object
+ required: [title, value]
+ properties:
+ title:
+ type: string
+ value:
+ type: string
+ style:
+ type: string
+ enum: [compact, expanded, filtered]
+ description: "compact=dropdown, expanded=radio/checkbox, filtered=searchable"
+ isMultiSelect:
+ type: boolean
+ value:
+ type: string
+ description: Default selected value(s)
+ placeholder:
+ type: string
+ wrap:
+ type: boolean
+ isRequired:
+ type: boolean
+ errorMessage:
+ type: string
+ label:
+ type: string
+
+ # ACTIONS
+
+ ActionSubmit:
+ name: Action.Submit
+ description: Submit form data to bot or webhook
+ category: cardActions
+ sdkBinding:
+ type: jsonSchema
+ elementType: Action.Submit
+ webStandardMapping:
+ htmlElement: button
+ ariaRole: button
+ semanticType: action
+ schema:
+ type: object
+ required: [type, title]
+ properties:
+ type:
+ type: string
+ const: Action.Submit
+ title:
+ type: string
+ description: Button text
+ data:
+ type: object
+ description: Data merged with input values on submit
+ iconUrl:
+ type: string
+ format: uri
+ style:
+ type: string
+ enum: [default, positive, destructive]
+ associatedInputs:
+ type: string
+ enum: [auto, none]
+ id:
+ type: string
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+
+ ActionOpenUrl:
+ name: Action.OpenUrl
+ description: Open a URL in new tab
+ category: cardActions
+ sdkBinding:
+ type: jsonSchema
+ elementType: Action.OpenUrl
+ webStandardMapping:
+ htmlElement: a
+ ariaRole: link
+ semanticType: navigation
+ schema:
+ type: object
+ required: [type, title, url]
+ properties:
+ type:
+ type: string
+ const: Action.OpenUrl
+ title:
+ type: string
+ url:
+ type: string
+ format: uri
+ iconUrl:
+ type: string
+ style:
+ type: string
+ id:
+ type: string
+
+ ActionShowCard:
+ name: Action.ShowCard
+ description: Reveal an inline sub-card
+ category: cardActions
+ sdkBinding:
+ type: jsonSchema
+ elementType: Action.ShowCard
+ schema:
+ type: object
+ required: [type, title, card]
+ properties:
+ type:
+ type: string
+ const: Action.ShowCard
+ title:
+ type: string
+ card:
+ type: object
+ description: Nested Adaptive Card
+ iconUrl:
+ type: string
+ style:
+ type: string
+ id:
+ type: string
+
+ ActionToggleVisibility:
+ name: Action.ToggleVisibility
+ description: Show/hide elements dynamically
+ category: cardActions
+ sdkBinding:
+ type: jsonSchema
+ elementType: Action.ToggleVisibility
+ schema:
+ type: object
+ required: [type, title]
+ properties:
+ type:
+ type: string
+ const: Action.ToggleVisibility
+ title:
+ type: string
+ targetElements:
+ type: array
+ description: IDs of elements to toggle
+ items:
+ type: string
+ id:
+ type: string
+
+ ActionExecute:
+ name: Action.Execute
+ description: Universal Action for bots (v1.4+)
+ category: cardActions
+ sdkBinding:
+ type: jsonSchema
+ elementType: Action.Execute
+ schema:
+ type: object
+ required: [type, title]
+ properties:
+ type:
+ type: string
+ const: Action.Execute
+ title:
+ type: string
+ verb:
+ type: string
+ description: Action identifier for bot
+ data:
+ type: object
+ iconUrl:
+ type: string
+ style:
+ type: string
+ associatedInputs:
+ type: string
+ enum: [auto, none]
+ id:
+ type: string
+
+extensionPoints:
+ - id: personal-tab
+ name: Personal Tab
+ type: tab
+ extensionType: iframe
+ description: |
+ Personal tab shown in user's personal app scope. Can be pinned
+ to left rail for quick access. Full web app in iframe with
+ Teams context via Teams JS SDK.
+ supportedComponents:
+ - all (custom HTML/CSS/JS)
+ constraints:
+ responsive: true
+ httpsRequired: true
+ maxWidth: 1920
+ maxHeight: 1080
+ context:
+ provides:
+ - userId
+ - userPrincipalName
+ - tenantId
+ - locale
+ - theme
+ - loginHint
+ - userObjectId
+ actions:
+ - authentication.authenticate
+ - dialog.open
+ - pages.getConfig
+ - app.getContext
+ extensionTypeConfig:
+ sdk: teams-js
+ initialization:
+ required: true
+ method: "app.initialize()"
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ - allow-same-origin
+ communication:
+ protocol: teams-js
+ globalObject: microsoftTeams
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/what-are-tabs
+
+ - id: channel-tab
+ name: Channel/Group Tab
+ type: tab
+ extensionType: iframe
+ description: |
+ Configurable tab in team channel or group chat. Supports
+ configuration page for initial setup. Shared across all
+ team/chat members.
+ supportedComponents:
+ - all (custom HTML/CSS/JS)
+ constraints:
+ responsive: true
+ httpsRequired: true
+ configurationRequired: true
+ context:
+ provides:
+ - channelId
+ - teamId
+ - groupId
+ - channelName
+ - teamName
+ - locale
+ - theme
+ - entityId
+ actions:
+ - pages.config.setConfig
+ - pages.config.setValidityState
+ - app.getContext
+ extensionTypeConfig:
+ sdk: teams-js
+ initialization:
+ required: true
+ method: "app.initialize()"
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ - allow-same-origin
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/create-channel-group-tab
+
+ - id: meeting-tab
+ name: Meeting Tab
+ type: tab
+ extensionType: iframe
+ description: |
+ Tab shown in Teams meeting (pre-meeting, in-meeting, or
+ post-meeting). Can access meeting context and participant info.
+ supportedComponents:
+ - all (custom HTML/CSS/JS)
+ constraints:
+ responsive: true
+ httpsRequired: true
+ context:
+ provides:
+ - meetingId
+ - conversationId
+ - organizerId
+ - meetingType
+ - userRole
+ actions:
+ - meeting.getMeetingDetails
+ - meeting.getAppContentStageSharingCapabilities
+ - meeting.shareAppContentToStage
+ extensionTypeConfig:
+ sdk: teams-js
+ capabilities:
+ - meeting
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/apps-in-teams-meetings/teams-apps-in-meetings
+
+ - id: bot-chat
+ name: Bot Conversation
+ type: bot
+ extensionType: jsonResponse
+ description: |
+ Conversational bot using Bot Framework. Sends and receives
+ Adaptive Cards for rich interactions. Supports 1:1, group chat,
+ and channel conversations.
+ supportedComponents:
+ - all Adaptive Card elements
+ - all Adaptive Card inputs
+ - all Adaptive Card actions
+ constraints:
+ maxCardSize: 28000
+ schemaVersion: "1.5"
+ responseTimeout: 15000
+ context:
+ provides:
+ - conversation
+ - activity
+ - turnContext
+ - userId
+ - channelId
+ actions:
+ - sendActivity
+ - updateActivity
+ - deleteActivity
+ - sendTypingIndicator
+ extensionTypeConfig:
+ sdk: botbuilder
+ protocol: botFramework
+ schemaFormat: adaptiveCard
+ schemaUrl: http://adaptivecards.io/schemas/adaptive-card.json
+ validation: true
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/bots/what-are-bots
+
+ - id: message-extension
+ name: Message Extension
+ type: messageExtension
+ extensionType: jsonResponse
+ description: |
+ Search and action commands in compose box and message overflow.
+ Returns Adaptive Cards or Hero Cards as search results or
+ action responses.
+ supportedComponents:
+ - all Adaptive Card elements (in cards returned)
+ constraints:
+ maxResults: 25
+ maxCardSize: 28000
+ context:
+ provides:
+ - commandId
+ - commandContext
+ - messagePayload
+ - queryParameters
+ actions:
+ - composeExtension.queryResponse
+ - task.submitResponse
+ extensionTypeConfig:
+ sdk: botbuilder
+ protocol: botFramework
+ commandTypes:
+ - query
+ - action
+ schemaFormat: adaptiveCard
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/messaging-extensions/what-are-messaging-extensions
+
+ - id: meeting-stage
+ name: Meeting Stage
+ type: meetingExtension
+ extensionType: iframe
+ description: |
+ Full-screen app experience shared to meeting stage. All
+ participants see the same view. Supports collaborative
+ scenarios like whiteboards, design reviews, etc.
+ supportedComponents:
+ - all (custom HTML/CSS/JS)
+ constraints:
+ responsive: true
+ httpsRequired: true
+ collaborative: true
+ context:
+ provides:
+ - meetingId
+ - frameContext: meetingStage
+ - shareToStage
+ actions:
+ - meeting.getAppContentStageSharingCapabilities
+ - meeting.getAppContentStageSharingState
+ extensionTypeConfig:
+ sdk: teams-js
+ capabilities:
+ - meeting
+ initialization:
+ method: "app.initialize()"
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/apps-in-teams-meetings/enable-and-configure-your-app-for-teams-meetings
+
+ - id: meeting-panel
+ name: Meeting Side Panel
+ type: meetingExtension
+ extensionType: iframe
+ description: |
+ Side panel shown during meeting. Personal view per participant.
+ Used for notes, polls, Q&A, resources, etc.
+ supportedComponents:
+ - all (custom HTML/CSS/JS)
+ constraints:
+ responsive: true
+ httpsRequired: true
+ maxWidth: 400
+ context:
+ provides:
+ - meetingId
+ - frameContext: sidePanel
+ - participantId
+ actions:
+ - meeting.getMeetingDetails
+ - meeting.getParticipant
+ extensionTypeConfig:
+ sdk: teams-js
+ capabilities:
+ - meeting
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/apps-in-teams-meetings/build-apps-for-teams-meeting-stage
+
+ - id: adaptive-card-message
+ name: Adaptive Card in Message
+ type: message
+ extensionType: jsonResponse
+ description: |
+ Standalone Adaptive Card posted to chat/channel by bot or
+ via webhook. Supports rich interactive content.
+ supportedComponents:
+ - all Adaptive Card elements
+ - all Adaptive Card inputs
+ - all Adaptive Card actions
+ constraints:
+ maxCardSize: 28000
+ schemaVersion: "1.5"
+ actionTypes:
+ - Action.Submit
+ - Action.OpenUrl
+ - Action.Execute
+ - Action.ToggleVisibility
+ context:
+ provides:
+ - cardId
+ - conversationId
+ actions:
+ - refreshCard
+ - updateCard
+ extensionTypeConfig:
+ schemaFormat: adaptiveCard
+ schemaUrl: http://adaptivecards.io/schemas/adaptive-card.json
+ validation: true
+ rendering: native
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-reference
+
+ - id: task-module
+ name: Task Module (Dialog)
+ type: dialog
+ extensionType: iframe
+ description: |
+ Modal dialog for focused tasks. Can show iframe or Adaptive
+ Card. Opened via Teams JS SDK or bot card action.
+ supportedComponents:
+ - all (iframe mode)
+ - all Adaptive Card elements (card mode)
+ constraints:
+ maxWidth: 600
+ maxHeight: 600
+ responsive: true
+ context:
+ provides:
+ - taskInfo
+ - completionBotId
+ actions:
+ - dialog.submit
+ - dialog.url.submit
+ extensionTypeConfig:
+ modes:
+ - iframe
+ - adaptiveCard
+ sdk: teams-js
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/what-are-task-modules
+
+policies:
+ componentRequirement:
+ level: required
+ scope: bots
+ rationale: |
+ Teams bots MUST use Adaptive Cards for rich interactive messages.
+ Plain text is supported but Adaptive Cards are required for UI.
+ Tabs are iframe-based and have no component requirement.
+
+ customComponents:
+ allowed: true
+ scope: tabs
+ constraints:
+ - httpsRequired
+ - sandboxOnly
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/create-personal-tab
+ rationale: |
+ Tabs are full web applications with complete freedom to use any
+ HTML/CSS/JS framework. Bots must use Adaptive Cards exclusively.
+
+ publishing:
+ sideloading:
+ name: Sideloading
+ componentRequirement: optional
+ customComponentsAllowed: true
+ reviewRequired: false
+ notes: |
+ Development/testing mode. Apps can be uploaded directly to
+ Teams tenant without review.
+
+ organizationStore:
+ name: Organization App Catalog
+ componentRequirement: required
+ customComponentsAllowed: true
+ reviewRequired: true
+ adminApprovalRequired: true
+ notes: |
+ Internal apps distributed within organization. IT admin
+ reviews and approves before catalog listing.
+
+ teamsStore:
+ name: Microsoft Teams Store
+ componentRequirement: required
+ customComponentsAllowed: true
+ reviewRequired: true
+ certificationRequired: true
+ securityReviewRequired: true
+ notes: |
+ Public app store distribution. Requires passing app validation,
+ security review, and compliance certification.
+ validationUrl: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/appsource/prepare/teams-store-validation-guidelines
+
+ designGuidelines:
+ required: true
+ designSystem: Fluent UI
+ designSystemUrl: https://developer.microsoft.com/en-us/fluentui
+ adaptiveCardsDesigner: https://adaptivecards.io/designer/
+ guidelines:
+ - Use Adaptive Cards Designer for card development
+ - Follow Fluent UI design principles for tabs
+ - Support light and dark themes
+ - Ensure mobile responsiveness
+ - Provide clear error messages
+ - Use appropriate card schema version
+ guidelinesUrl: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/design/design-teams-app-overview
+
+ security:
+ httpsRequired: true
+ authenticationRequired: false
+ ssoSupported: true
+ description: |
+ All tab URLs must use HTTPS. Teams supports SSO via Azure AD.
+ Bots use Bot Framework authentication. Apps can request
+ resource-specific consent (RSC) permissions.
+ rscPermissions:
+ - TeamSettings.Read.Group
+ - ChannelMessage.Read.Group
+ - TeamsActivity.Send
+ - ChatMessage.Read.Chat
+ - OnlineMeeting.ReadBasic.Chat
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/authentication/authentication
+
+renderingEngines:
+ adaptive-cards-native:
+ type: native
+ name: Adaptive Cards Native Renderer
+ description: |
+ Teams natively renders Adaptive Cards sent by bots, message
+ extensions, and webhooks. Cards are defined as JSON and rendered
+ consistently across Teams desktop, mobile, and web.
+ schemaSupport:
+ dataSchema: adaptiveCard
+ schemaUrl: http://adaptivecards.io/schemas/adaptive-card.json
+ version: "1.5"
+ customRenderers: false
+ platforms:
+ - Teams Desktop (Windows, macOS, Linux)
+ - Teams Mobile (iOS, Android)
+ - Teams Web
+ - Outlook Desktop
+ - Outlook Web
+ - Microsoft 365 App
+
+ teams-tab-iframe:
+ type: custom
+ name: Teams Tab Iframe Renderer
+ description: |
+ Tabs are rendered as web pages in sandboxed iframes. Developers
+ have full control over HTML/CSS/JS. Teams JS SDK provides bridge
+ to Teams context and capabilities.
+ sandboxing:
+ iframeSandbox: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ - allow-same-origin
+ cspPolicy: "Must allow https://teams.microsoft.com as frame-ancestor"
+ platforms:
+ - Teams Desktop (Windows, macOS, Linux)
+ - Teams Mobile (iOS, Android)
+ - Teams Web
+
+jsonFormsIntegration:
+ supported: true
+ scope: tabs
+ notes: |
+ Tabs can use JSON Forms or any other form library since they're
+ full web apps. Adaptive Cards have their own input system.
+
+mcpAppsIntegration:
+ supported: false
+ notes: |
+ Not currently integrated with MCP Apps specification.
+
+extensionType: hybrid
+
+extensions:
+ declarativeSchemas:
+ enabled: true
+ scope: adaptiveCards
+ schemaFormat: json
+ description: |
+ Adaptive Cards are entirely JSON-based declarative UI. Bots
+ construct cards as JSON conforming to Adaptive Card schema.
+ validation:
+ designerTool: https://adaptivecards.io/designer/
+ sdkValidation: true
+ runtimeValidation: true
+ schemaUrl: http://adaptivecards.io/schemas/adaptive-card.json
+ schemaVersions:
+ - "1.0"
+ - "1.2"
+ - "1.3"
+ - "1.4"
+ - "1.5"
+ fallbackSupport: true
+ documentation: https://adaptivecards.io/
+
+ i18n:
+ enabled: true
+ localeDetection: automatic
+ description: |
+ Teams provides user locale via Teams JS SDK context. Apps can
+ localize tab content, bot messages, and Adaptive Card text.
+ implementation:
+ clientProvides:
+ - locale
+ - userLocale
+ - osLocale
+ developerResponsibility:
+ - Localize tab UI
+ - Localize Adaptive Card text
+ - Localize bot messages
+ - Handle RTL languages
+ - Format dates/times/numbers per locale
+ supportedLocales:
+ - en-US
+ - en-GB
+ - es-ES
+ - es-MX
+ - fr-FR
+ - fr-CA
+ - de-DE
+ - it-IT
+ - ja-JP
+ - ko-KR
+ - pt-BR
+ - ru-RU
+ - zh-CN
+ - zh-TW
+ - ar-SA
+ - cs-CZ
+ - da-DK
+ - nl-NL
+ - fi-FI
+ - he-IL
+ - hi-IN
+ - hu-HU
+ - id-ID
+ - nb-NO
+ - pl-PL
+ - pt-PT
+ - ro-RO
+ - sv-SE
+ - th-TH
+ - tr-TR
+ - uk-UA
+ - vi-VN
+ appManifest:
+ localizationInfoRequired: true
+ additionalLanguagesField: true
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/build-and-test/apps-localization
+
+ compliance:
+ enabled: true
+ description: |
+ Apps distributed via Teams Store must pass Microsoft's app
+ validation, security review, and compliance certification.
+ requirements:
+ appValidation:
+ required: true
+ scope: teamsStore
+ includes:
+ - Manifest validation
+ - Functionality testing
+ - Performance testing
+ - UI/UX review
+ - Content policy compliance
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/appsource/prepare/teams-store-validation-guidelines
+
+ securityReview:
+ required: true
+ scope: teamsStore
+ includes:
+ - Data handling and privacy
+ - Authentication security
+ - API usage patterns
+ - Permission scope audit
+ - Vulnerability assessment
+
+ publisherVerification:
+ required: true
+ scope: teamsStore
+ description: |
+ Publisher must verify identity via Microsoft Partner Center.
+ Shows blue verified badge in app listing.
+
+ publisherAttestation:
+ required: true
+ scope: teamsStore
+ description: |
+ Publisher attests to security, privacy, and compliance practices.
+
+ certifications:
+ microsoft365Certification:
+ available: true
+ tier: certified
+ description: |
+ Apps can achieve Microsoft 365 Certified status by passing
+ comprehensive security, compliance, and privacy assessments.
+ url: https://learn.microsoft.com/en-us/microsoft-365-app-certification/overview
+
+ cloudSecurityAlliance:
+ available: true
+ description: CSA STAR attestation available
+
+ iso27001:
+ available: true
+ description: ISO 27001 certification for data security
+
+ soc2:
+ available: true
+ description: SOC 2 Type II attestation
+
+ dataResidency:
+ supported: true
+ description: |
+ Teams supports data residency commitments for enterprise
+ customers via Microsoft 365 data location settings.
+
+ documentation: https://learn.microsoft.com/en-us/microsoft-365-app-certification/docs/enterprise-app-certification-guide
+
+ manifest:
+ file: manifest.json
+ description: |
+ Every Teams app requires a manifest.json file defining app
+ metadata, capabilities, permissions, and resource URLs.
+ schema: https://developer.microsoft.com/json-schemas/teams/v1.24/MicrosoftTeams.schema.json
+ currentVersion: "1.24"
+ packageFormat: .zip
+ packageContents:
+ - manifest.json
+ - color.png (192x192)
+ - outline.png (32x32)
+ keyProperties:
+ - id: Unique app ID (GUID)
+ - version: App version
+ - packageName: Reverse domain notation
+ - developer: Publisher info
+ - name: App name (short, full)
+ - description: App description (short, full)
+ - icons: App icons
+ - accentColor: Brand color (hex)
+ - configurableTabs: Channel/group tabs
+ - staticTabs: Personal tabs
+ - bots: Bot configuration
+ - composeExtensions: Message extensions
+ - permissions: Requested permissions
+ - validDomains: Allowed domains
+ - webApplicationInfo: SSO configuration
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema
+
+ analytics:
+ enabled: true
+ description: |
+ Teams provides app analytics in Partner Center showing usage,
+ installations, active users, and engagement metrics.
+ metrics:
+ - Daily/Monthly Active Users (DAU/MAU)
+ - Installations and uninstalls
+ - User retention
+ - Feature usage
+ - Platform distribution (desktop/mobile/web)
+ - Geographic distribution
+ - Tenant size distribution
+ dashboard: https://partner.microsoft.com/dashboard/
+ customTelemetry:
+ supported: true
+ description: Apps can implement custom telemetry using Application Insights
+
+ testing:
+ enabled: true
+ description: Tools and methods for testing Teams apps
+ tools:
+ adaptiveCardsDesigner:
+ url: https://adaptivecards.io/designer/
+ description: Visual designer for Adaptive Cards with live preview
+ features:
+ - Visual card composition
+ - JSON export/import
+ - Sample data binding
+ - Host config preview
+ - Validation errors
+
+ teamsAppStudio:
+ deprecated: true
+ replacement: Teams Developer Portal
+ description: Legacy tool replaced by Developer Portal
+
+ developerPortal:
+ url: https://dev.teams.microsoft.com/
+ description: Web-based app management and testing platform
+ features:
+ - App manifest editor
+ - Validation tools
+ - Test in Teams
+ - App submission
+ - Analytics
+
+ teamsToolkit:
+ url: https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/teams-toolkit-fundamentals
+ description: VS Code extension for Teams app development
+ features:
+ - Project scaffolding
+ - Local debugging
+ - Azure provisioning
+ - CI/CD integration
+ - Sample apps
+
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/build-and-test/test-app-overview
+
+ accessibilityFeatures:
+ keyboardNavigation: true
+ screenReaderSupport: true
+ highContrastMode: true
+ description: |
+ Teams platform provides built-in accessibility for Adaptive Cards.
+ Tab apps must implement their own accessibility features.
+ adaptiveCardsAccessibility:
+ - Automatic screen reader support
+ - Keyboard navigation built-in
+ - High contrast theme support
+ - Focus management
+ - ARIA attributes generated
+ tabAccessibility:
+ - Developer must implement WCAG 2.1 AA compliance
+ - Use semantic HTML
+ - Provide ARIA labels
+ - Ensure keyboard navigation
+ - Support high contrast themes
+ - Test with screen readers
+ guidelines:
+ - Use label property on Adaptive Card inputs (v1.3+)
+ - Provide alt text for images
+ - Ensure sufficient color contrast
+ - Support keyboard-only navigation
+ - Provide skip links in tabs
+ - Test with Narrator, JAWS, NVDA
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/design/design-teams-app-accessibility
+
+ rateLimits:
+ description: Rate limits for Teams platform APIs
+ limits:
+ botMessages:
+ rate: "1 message per second per conversation"
+ burst: "Up to 10 messages burst"
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/rate-limit
+
+ graphApi:
+ rate: "Varies by endpoint and tenant"
+ description: Microsoft Graph API has per-app and per-tenant limits
+ documentation: https://learn.microsoft.com/en-us/graph/throttling
+
+ adaptiveCardRefresh:
+ rate: "1 refresh per 60 seconds per user per card"
+
+ messageExtensionQueries:
+ rate: "5 queries per second per user"
+
+ retryPolicy: "Use exponential backoff with jitter"
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/rate-limit
+
+ securityFeatures:
+ authentication:
+ aadSsoSupported: true
+ oauthSupported: true
+ description: |
+ Teams supports SSO via Azure AD. Tabs can use Teams JS SDK
+ authentication namespace. Bots use Bot Framework auth.
+
+ permissions:
+ rscPermissions: true
+ description: |
+ Resource-specific consent allows apps to request granular
+ permissions for team/chat resources without admin consent.
+
+ contentSecurityPolicy:
+ required: true
+ frameAncestors: "Must allow https://teams.microsoft.com"
+
+ features:
+ - Azure AD SSO
+ - OAuth 2.0 support
+ - Resource-specific consent (RSC)
+ - Bot authentication via Bot Framework
+ - Token exchange for seamless auth
+ - Secure iframe sandboxing
+ - HTTPS requirement for all endpoints
+
+ documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/authentication/authentication
+
+notes: |
+ Microsoft Teams represents a hybrid extensibility platform combining:
+
+ 1. **Adaptive Cards** (Declarative JSON):
+ - Used by bots and message extensions
+ - JSON-based declarative UI (similar to Slack Block Kit)
+ - Native rendering across Teams, Outlook, Microsoft 365
+ - Schema version 1.5 with rich elements and actions
+ - Required for bot messages with UI
+
+ 2. **Tabs** (Iframe-based):
+ - Full web applications in sandboxed iframes
+ - Complete freedom with HTML/CSS/JS frameworks
+ - Teams JS SDK provides context and capabilities
+ - Personal, channel/group, and meeting scopes
+ - Can extend to Outlook and Microsoft 365 app
+
+ 3. **Bots** (Conversational + Cards):
+ - Built on Microsoft Bot Framework
+ - Send/receive Adaptive Cards for rich interactions
+ - Support 1:1, group chat, channel conversations
+ - Can be proactive or reactive
+
+ 4. **Message Extensions**:
+ - Search and action commands
+ - Extend compose box and message overflow menu
+ - Return Adaptive Cards as results
+ - Built on Bot Framework protocol
+
+ 5. **Meeting Extensions**:
+ - In-meeting apps, stages, and side panels
+ - Meeting stage for collaborative experiences
+ - Side panels for personal tools
+ - Pre-meeting and post-meeting tabs
+
+ Key platform characteristics:
+ - Hybrid model: Declarative (Adaptive Cards) + Custom (Tabs)
+ - Cross-Microsoft 365: Works in Teams, Outlook, M365 app
+ - Modern SDK: TeamsJS v2+ with tree-shaking support
+ - Enterprise-ready: Comprehensive compliance and security
+ - Global reach: 40+ supported locales
+ - Accessibility: Built-in for cards, developer-implemented for tabs
+
+ Development tools:
+ - Adaptive Cards Designer for visual card building
+ - Teams Developer Portal for app management
+ - Teams Toolkit for VS Code
+ - Comprehensive documentation and samples
+
+metadata:
+ fenestra:
+ createdAt: "2025-12-30"
+ author: "Fenestra Specification Team"
+ category: "Collaboration Platform"
+ tags:
+ - collaboration
+ - microsoft-365
+ - adaptive-cards
+ - iframe
+ - bots
+ - meetings
+ - hybrid
+ relatedPlatforms:
+ - Slack (similar declarative UI with Block Kit)
+ - Discord (bots and embeds)
+ - Zoom Apps (meeting extensions)
+ references:
+ - https://learn.microsoft.com/en-us/microsoftteams/platform/
+ - https://adaptivecards.io/
+ - https://learn.microsoft.com/en-us/javascript/api/overview/msteams-client
+ - https://dev.botframework.com/
diff --git a/specs/fenestra/examples/0.1.0/vscode.fenestra.yaml b/specs/fenestra/examples/0.1.0/vscode.fenestra.yaml
new file mode 100644
index 0000000..de7ea7f
--- /dev/null
+++ b/specs/fenestra/examples/0.1.0/vscode.fenestra.yaml
@@ -0,0 +1,1184 @@
+# Fenestra Document: Visual Studio Code Extension Platform
+#
+# VS Code represents a dual-execution model with Extension Host + Webview architecture.
+# Extensions run in a Node.js Extension Host process with access to the vscode API,
+# while custom UI can be rendered in sandboxed Webview iframes.
+
+fenestra: "0.1.0"
+
+info:
+ title: Visual Studio Code Extension Platform
+ version: "1.0.0"
+ description: |
+ Visual Studio Code's Extension API enables developers to extend the editor
+ with new functionality through a dual-architecture model.
+
+ Key characteristics:
+ - Extension Host process (Node.js) for extension logic and VS Code API access
+ - Webview panels (sandboxed iframes) for custom HTML/CSS/JS UI
+ - Communication via postMessage between Extension Host and Webviews
+ - Webview UI Toolkit for consistent, accessible UI components
+ - Multiple contribution points (commands, views, editors, etc.)
+ - Rich extension capabilities: language support, debugging, source control, and more
+
+ contact:
+ name: VS Code Team
+ url: https://code.visualstudio.com/api
+ email: vscode@microsoft.com
+
+platform:
+ name: Visual Studio Code
+ vendor: Microsoft Corporation
+ documentation: https://code.visualstudio.com/api
+ appMarketplace: https://marketplace.visualstudio.com/vscode
+
+sdks:
+ vscode-api:
+ name: VS Code Extension API
+ packageManager: npm
+ package: "vscode"
+ typesPackage: "@types/vscode"
+ version: "^1.85.0"
+ documentation: https://code.visualstudio.com/api/references/vscode-api
+ description: |
+ The core VS Code Extension API. Extensions import this module to access
+ all VS Code capabilities including commands, windows, editors, workspace,
+ languages, debugging, and more.
+
+ Note: The 'vscode' module is provided by the Extension Host runtime and
+ should be declared as a dependency but not bundled.
+ exports:
+ commands:
+ type: utility
+ description: Execute and register commands (namespace)
+ window:
+ type: utility
+ description: Window management, UI elements, messages, input boxes (namespace)
+ workspace:
+ type: utility
+ description: Workspace folders, file system, configuration (namespace)
+ languages:
+ type: utility
+ description: Language features, diagnostics, hover, completion (namespace)
+ debug:
+ type: utility
+ description: Debugging sessions and configurations (namespace)
+ scm:
+ type: utility
+ description: Source control management (namespace)
+ extensions:
+ type: utility
+ description: Access to other extensions (namespace)
+ TreeView:
+ type: type
+ description: Tree view in sidebar or panel (class)
+ TreeDataProvider:
+ type: type
+ description: Data provider for tree views (interface)
+ WebviewPanel:
+ type: type
+ description: Webview panel with custom HTML content (interface)
+ CustomTextEditorProvider:
+ type: type
+ description: Custom editor for text files (interface)
+ CustomReadonlyEditorProvider:
+ type: type
+ description: Custom read-only editor provider (interface)
+ StatusBarItem:
+ type: type
+ description: Status bar item (class)
+ QuickPick:
+ type: type
+ description: Quick pick UI for user selection (interface)
+ InputBox:
+ type: type
+ description: Input box for user text entry (interface)
+ Uri:
+ type: type
+ description: Universal resource identifier (class)
+ Range:
+ type: type
+ description: Text range with start and end positions (class)
+ Position:
+ type: type
+ description: Position in a text document (class)
+ TextDocument:
+ type: type
+ description: Text document representation (interface)
+
+ webview-ui-toolkit:
+ name: Webview UI Toolkit
+ packageManager: npm
+ package: "@vscode/webview-ui-toolkit"
+ version: "^1.4.0"
+ repository: https://github.com/microsoft/vscode-webview-ui-toolkit
+ documentation: https://github.com/microsoft/vscode-webview-ui-toolkit/blob/main/docs/getting-started.md
+ description: |
+ A component library for building webview-based extensions. Provides
+ Web Components that match VS Code's look and feel with built-in theming
+ support (light, dark, high contrast).
+
+ Uses FAST Foundation under the hood for accessible, performant components.
+ exports:
+ provideVSCodeDesignSystem:
+ type: utility
+ description: Initialize the design system for webview (function)
+ vsCodeButton:
+ type: component
+ description: Button component
+ vsCodeCheckbox:
+ type: component
+ description: Checkbox component
+ vsCodeDataGrid:
+ type: component
+ description: Data grid/table component
+ vsCodeDropdown:
+ type: component
+ description: Dropdown/select component
+ vsCodeLink:
+ type: component
+ description: Hyperlink component
+ vsCodeOption:
+ type: component
+ description: Option for dropdowns
+ vsCodePanels:
+ type: component
+ description: Tab panels container
+ vsCodeProgressRing:
+ type: component
+ description: Loading spinner
+ vsCodeRadio:
+ type: component
+ description: Radio button
+ vsCodeRadioGroup:
+ type: component
+ description: Radio button group
+ vsCodeTextArea:
+ type: component
+ description: Multi-line text input
+ vsCodeTextField:
+ type: component
+ description: Single-line text input
+ vsCodeDivider:
+ type: component
+ description: Visual divider
+ vsCodeBadge:
+ type: component
+ description: Badge/pill component
+ vsCodeTag:
+ type: component
+ description: Tag component
+
+ yeoman-generator:
+ name: Yeoman VS Code Extension Generator
+ packageManager: npm
+ package: "generator-code"
+ version: "^1.8.0"
+ repository: https://github.com/microsoft/vscode-generator-code
+ documentation: https://code.visualstudio.com/api/get-started/your-first-extension
+ description: |
+ Yeoman generator for scaffolding new VS Code extensions.
+ Supports TypeScript, JavaScript, and various extension types.
+ starterTemplate:
+ command: "npm install -g yo generator-code && yo code"
+ documentation: https://code.visualstudio.com/api/get-started/your-first-extension
+
+ vsce:
+ name: Visual Studio Code Extensions CLI
+ packageManager: npm
+ package: "@vscode/vsce"
+ version: "^2.22.0"
+ repository: https://github.com/microsoft/vscode-vsce
+ documentation: https://code.visualstudio.com/api/working-with-extensions/publishing-extension
+ description: |
+ Command-line tool for packaging, publishing, and managing VS Code extensions.
+ cliTool:
+ package: "@vscode/vsce"
+ globalInstall: true
+ commands:
+ package: "Package extension into .vsix file"
+ publish: "Publish extension to marketplace"
+ ls: "List packaged files"
+
+componentCatalog:
+ categories:
+ action:
+ name: Actions
+ description: Interactive button and action components
+ components: [button, link]
+
+ input:
+ name: Inputs
+ description: Form input controls
+ components: [textField, textArea, dropdown, checkbox, radio, radioGroup]
+
+ data:
+ name: Data Display
+ description: Components for displaying data
+ components: [dataGrid, badge, tag, progressRing]
+
+ layout:
+ name: Layout
+ description: Layout and container components
+ components: [panels, divider]
+
+ treeView:
+ name: Tree Views
+ description: Hierarchical tree view components
+ components: [treeView, treeItem]
+
+ editor:
+ name: Editor Components
+ description: Editor-related UI components
+ components: [statusBarItem, quickPick, inputBox]
+
+ components:
+ button:
+ name: Button
+ description: VS Code styled button for webviews
+ category: action
+ sdkBinding:
+ sdk: webview-ui-toolkit
+ export: vsCodeButton
+ webStandardMapping:
+ htmlElement: button
+ ariaRole: button
+ semanticType: action
+ props:
+ appearance:
+ type: string
+ enum: [primary, secondary, icon]
+ description: Button visual style
+ disabled:
+ type: boolean
+ description: Whether button is disabled
+ autofocus:
+ type: boolean
+ description: Auto-focus on load
+ variants:
+ - primary
+ - secondary
+ - icon
+ examples:
+ - title: Primary Button
+ code: |
+ Click Me
+ language: html
+ - title: Icon Button
+ code: |
+
+
+
+ language: html
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ ariaSupport: true
+
+ textField:
+ name: Text Field
+ description: Single-line text input
+ category: input
+ sdkBinding:
+ sdk: webview-ui-toolkit
+ export: vsCodeTextField
+ webStandardMapping:
+ htmlElement: input
+ inputType: text
+ ariaRole: textbox
+ semanticType: input
+ props:
+ value:
+ type: string
+ description: Input value
+ placeholder:
+ type: string
+ description: Placeholder text
+ disabled:
+ type: boolean
+ readonly:
+ type: boolean
+ maxlength:
+ type: number
+ examples:
+ - title: Basic Text Field
+ code: |
+
+ language: html
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ labelRequired: true
+
+ textArea:
+ name: Text Area
+ description: Multi-line text input
+ category: input
+ sdkBinding:
+ sdk: webview-ui-toolkit
+ export: vsCodeTextArea
+ webStandardMapping:
+ htmlElement: textarea
+ ariaRole: textbox
+ semanticType: input
+ props:
+ value:
+ type: string
+ placeholder:
+ type: string
+ rows:
+ type: number
+ cols:
+ type: number
+ resize:
+ type: string
+ enum: [none, both, horizontal, vertical]
+ examples:
+ - title: Text Area
+ code: |
+
+
+ language: html
+
+ dropdown:
+ name: Dropdown
+ description: Dropdown select menu
+ category: input
+ sdkBinding:
+ sdk: webview-ui-toolkit
+ export: vsCodeDropdown
+ webStandardMapping:
+ htmlElement: select
+ ariaRole: listbox
+ semanticType: input
+ props:
+ disabled:
+ type: boolean
+ position:
+ type: string
+ enum: [above, below]
+ examples:
+ - title: Dropdown
+ code: |
+
+ Option 1
+ Option 2
+ Option 3
+
+ language: html
+
+ checkbox:
+ name: Checkbox
+ description: Checkbox input
+ category: input
+ sdkBinding:
+ sdk: webview-ui-toolkit
+ export: vsCodeCheckbox
+ webStandardMapping:
+ htmlElement: input[type="checkbox"]
+ ariaRole: checkbox
+ semanticType: input
+ props:
+ checked:
+ type: boolean
+ disabled:
+ type: boolean
+ examples:
+ - title: Checkbox
+ code: |
+ Enable feature
+ language: html
+
+ radio:
+ name: Radio Button
+ description: Single radio button
+ category: input
+ sdkBinding:
+ sdk: webview-ui-toolkit
+ export: vsCodeRadio
+ webStandardMapping:
+ htmlElement: input[type="radio"]
+ ariaRole: radio
+ semanticType: input
+ examples:
+ - title: Radio Button
+ code: |
+ Choice 1
+ language: html
+
+ radioGroup:
+ name: Radio Group
+ description: Group of radio buttons
+ category: input
+ sdkBinding:
+ sdk: webview-ui-toolkit
+ export: vsCodeRadioGroup
+ webStandardMapping:
+ ariaRole: radiogroup
+ semanticType: input
+ examples:
+ - title: Radio Group
+ code: |
+
+
+ Option 1
+ Option 2
+ Option 3
+
+ language: html
+
+ dataGrid:
+ name: Data Grid
+ description: Table/grid for displaying data
+ category: data
+ sdkBinding:
+ sdk: webview-ui-toolkit
+ export: vsCodeDataGrid
+ webStandardMapping:
+ htmlElement: table
+ ariaRole: grid
+ semanticType: display
+ props:
+ gridTemplateColumns:
+ type: string
+ description: CSS grid template columns
+ generateHeader:
+ type: string
+ enum: [default, none, sticky]
+ examples:
+ - title: Data Grid
+ code: |
+
+
+ Name
+ Value
+
+
+ Item 1
+ 100
+
+
+ language: html
+
+ panels:
+ name: Panels
+ description: Tab panels for organizing content
+ category: layout
+ sdkBinding:
+ sdk: webview-ui-toolkit
+ export: vsCodePanels
+ webStandardMapping:
+ ariaRole: tablist
+ semanticType: navigation
+ examples:
+ - title: Tab Panels
+ code: |
+
+ Tab 1
+ Tab 2
+ Content 1
+ Content 2
+
+ language: html
+
+ badge:
+ name: Badge
+ description: Badge/pill component for counts or status
+ category: data
+ sdkBinding:
+ sdk: webview-ui-toolkit
+ export: vsCodeBadge
+ webStandardMapping:
+ htmlElement: span
+ semanticType: display
+ examples:
+ - title: Badge
+ code: |
+ 5
+ language: html
+
+ divider:
+ name: Divider
+ description: Visual separator
+ category: layout
+ sdkBinding:
+ sdk: webview-ui-toolkit
+ export: vsCodeDivider
+ webStandardMapping:
+ htmlElement: hr
+ ariaRole: separator
+ semanticType: layout
+ examples:
+ - title: Divider
+ code: |
+
+ language: html
+
+ progressRing:
+ name: Progress Ring
+ description: Loading/progress indicator
+ category: data
+ sdkBinding:
+ sdk: webview-ui-toolkit
+ export: vsCodeProgressRing
+ webStandardMapping:
+ ariaRole: progressbar
+ semanticType: display
+ examples:
+ - title: Progress Ring
+ code: |
+
+ language: html
+
+ treeView:
+ name: Tree View
+ description: Hierarchical tree view in sidebar or panel
+ category: treeView
+ sdkBinding:
+ sdk: vscode-api
+ export: TreeView
+ examples:
+ - title: Tree View Registration
+ code: |
+ const treeDataProvider = new MyTreeDataProvider();
+ const treeView = vscode.window.createTreeView('myView', {
+ treeDataProvider
+ });
+ language: typescript
+
+ statusBarItem:
+ name: Status Bar Item
+ description: Item in the status bar
+ category: editor
+ sdkBinding:
+ sdk: vscode-api
+ export: StatusBarItem
+ examples:
+ - title: Status Bar Item
+ code: |
+ const statusBarItem = vscode.window.createStatusBarItem(
+ vscode.StatusBarAlignment.Right,
+ 100
+ );
+ statusBarItem.text = "$(check) Ready";
+ statusBarItem.show();
+ language: typescript
+
+ quickPick:
+ name: Quick Pick
+ description: Quick pick UI for user selection
+ category: editor
+ sdkBinding:
+ sdk: vscode-api
+ export: QuickPick
+ examples:
+ - title: Quick Pick
+ code: |
+ const quickPick = vscode.window.createQuickPick();
+ quickPick.items = [
+ { label: 'Option 1' },
+ { label: 'Option 2' }
+ ];
+ quickPick.onDidChangeSelection(selection => {
+ console.log(selection[0].label);
+ });
+ quickPick.show();
+ language: typescript
+
+policies:
+ componentRequirement:
+ level: recommended
+ scope: all
+ rationale: |
+ VS Code API is REQUIRED for extension functionality, but UI components
+ are RECOMMENDED, not required. The Webview UI Toolkit is recommended
+ for webviews to ensure consistent look and feel, but developers can
+ use custom HTML/CSS or other frameworks.
+
+ customComponents:
+ allowed: true
+ constraints:
+ - sandboxOnly
+ registrationRequired: false
+ approvalRequired: false
+ documentation: https://code.visualstudio.com/api/extension-guides/webview
+ rationale: |
+ Extensions can use custom UI in webviews. The Extension Host runs
+ extension code in a Node.js process with VS Code API access, while
+ webviews run custom HTML/CSS/JS in sandboxed iframes.
+
+ publishing:
+ privateExtensions:
+ componentRequirement: optional
+ customComponentsAllowed: true
+ reviewRequired: false
+ notes: |
+ Private extensions (.vsix files) can be installed locally or
+ distributed privately without marketplace review.
+
+ publicExtensions:
+ componentRequirement: optional
+ customComponentsAllowed: true
+ reviewRequired: true
+ notes: |
+ Public marketplace extensions undergo automated and manual review
+ for security, quality, and adherence to guidelines.
+
+ verifiedPublisher:
+ certificationRequired: true
+ notes: |
+ Verified publisher status requires domain verification and
+ adherence to publisher agreement.
+
+ designGuidelines:
+ required: false
+ designSystem: "Webview UI Toolkit"
+ designSystemUrl: https://github.com/microsoft/vscode-webview-ui-toolkit
+ designTokensProvided: true
+ guidelines:
+ - Use Webview UI Toolkit for consistent theming
+ - Support light, dark, and high contrast themes
+ - Follow VS Code UX guidelines for extensions
+ - Use Codicons for icons
+ - Ensure keyboard accessibility
+
+ security:
+ sandbox: true
+ sandboxDescription: |
+ Webviews run in sandboxed iframes with limited permissions.
+ Extension Host code runs in a separate Node.js process.
+ Communication between Extension Host and Webview uses postMessage.
+ cspPolicy: "default-src 'none'; style-src ${webview.cspSource} 'unsafe-inline'; script-src 'nonce-${nonce}' ${webview.cspSource}; img-src ${webview.cspSource} https: data:;"
+ securityGuidelines: https://code.visualstudio.com/api/extension-guides/webview#security
+
+extensionPoints:
+ - id: sidebar-webview
+ name: Sidebar Webview Panel
+ type: sidebar
+ extensionType: iframe
+ description: |
+ Custom webview panel in the sidebar. Extensions register a view
+ in the activity bar and provide webview content.
+ supportedComponents:
+ - all webview components
+ constraints:
+ resizable: true
+ responsive: true
+ context:
+ provides:
+ - workspace
+ - activeEditor
+ - selection
+ - theme
+ actions:
+ - postMessage
+ - receiveMessage
+ - setState
+ - getState
+ extensionTypeConfig:
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ communication:
+ globalObject: "acquireVsCodeApi"
+ initialization:
+ method: "acquireVsCodeApi() in webview"
+ async: false
+ asyncPattern: promises
+ capabilities:
+ context: true
+ uiActions: true
+ dataActions: true
+ events: true
+ examples:
+ - title: Webview Panel Registration
+ code: |
+ const provider = {
+ resolveWebviewView(webviewView) {
+ webviewView.webview.options = {
+ enableScripts: true
+ };
+ webviewView.webview.html = getWebviewContent();
+ }
+ };
+ vscode.window.registerWebviewViewProvider('myView', provider);
+ language: typescript
+
+ - id: editor-webview
+ name: Editor Webview Panel
+ type: panel
+ extensionType: iframe
+ description: |
+ Standalone webview panel that opens in the editor area.
+ Can be used for custom editors, dashboards, or tools.
+ supportedComponents:
+ - all webview components
+ constraints:
+ resizable: true
+ responsive: true
+ multiple: true
+ context:
+ provides:
+ - workspace
+ - theme
+ actions:
+ - postMessage
+ - receiveMessage
+ - setState
+ - getState
+ extensionTypeConfig:
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ communication:
+ globalObject: "acquireVsCodeApi"
+ examples:
+ - title: Create Webview Panel
+ code: |
+ const panel = vscode.window.createWebviewPanel(
+ 'myPanel',
+ 'My Panel',
+ vscode.ViewColumn.One,
+ {
+ enableScripts: true
+ }
+ );
+ panel.webview.html = getWebviewContent();
+ language: typescript
+
+ - id: custom-editor
+ name: Custom Editor
+ type: panel
+ extensionType: codedComponents
+ description: |
+ Custom editor for specific file types. Can be text-based or
+ fully custom webview-based editor.
+ supportedComponents:
+ - all webview components (for webview editors)
+ constraints:
+ fileTypes: true
+ multiple: true
+ context:
+ provides:
+ - document
+ - workspace
+ - theme
+ actions:
+ - edit
+ - save
+ - undo
+ - redo
+ extensionTypeConfig:
+ sdk: vscode-api
+ runtime:
+ type: directExecution
+ bundling: developerBuild
+ examples:
+ - title: Custom Text Editor
+ code: |
+ class MyEditorProvider implements vscode.CustomTextEditorProvider {
+ resolveCustomTextEditor(document, webviewPanel) {
+ webviewPanel.webview.options = {
+ enableScripts: true
+ };
+ webviewPanel.webview.html = getEditorHtml();
+ }
+ }
+ vscode.window.registerCustomEditorProvider(
+ 'myEditor.edit',
+ new MyEditorProvider()
+ );
+ language: typescript
+
+ - id: tree-view
+ name: Tree View
+ type: sidebar
+ extensionType: codedComponents
+ description: |
+ Hierarchical tree view in sidebar or panel. Uses TreeDataProvider
+ to supply data, VS Code renders the tree natively.
+ supportedComponents:
+ - treeView
+ - treeItem
+ constraints:
+ resizable: true
+ collapsible: true
+ context:
+ provides:
+ - selection
+ - workspace
+ actions:
+ - reveal
+ - refresh
+ extensionTypeConfig:
+ sdk: vscode-api
+ runtime:
+ type: directExecution
+ bundling: developerBuild
+ examples:
+ - title: Tree View
+ code: |
+ class MyTreeDataProvider implements vscode.TreeDataProvider {
+ getTreeItem(element) {
+ return element;
+ }
+ getChildren(element) {
+ return this.getChildElements(element);
+ }
+ }
+ vscode.window.createTreeView('myView', {
+ treeDataProvider: new MyTreeDataProvider()
+ });
+ language: typescript
+
+ - id: status-bar
+ name: Status Bar
+ type: toolbar
+ extensionType: codedComponents
+ description: |
+ Items in the status bar at the bottom of the window.
+ Can show text, icons, and be clickable.
+ supportedComponents:
+ - statusBarItem
+ constraints:
+ alignment: true
+ priority: true
+ context:
+ provides:
+ - workspace
+ - activeEditor
+ actions:
+ - show
+ - hide
+ - dispose
+ extensionTypeConfig:
+ sdk: vscode-api
+ examples:
+ - title: Status Bar Item
+ code: |
+ const item = vscode.window.createStatusBarItem(
+ vscode.StatusBarAlignment.Right,
+ 100
+ );
+ item.text = "$(rocket) Extension";
+ item.command = 'extension.command';
+ item.show();
+ language: typescript
+
+ - id: activity-bar
+ name: Activity Bar
+ type: toolbar
+ extensionType: codedComponents
+ description: |
+ Icon in the activity bar (left side) that opens a view container
+ in the sidebar. Defined via package.json contribution points.
+ supportedComponents: []
+ constraints:
+ iconRequired: true
+ context:
+ provides:
+ - viewContainer
+ extensionTypeConfig:
+ sdk: vscode-api
+
+ - id: quick-pick
+ name: Quick Pick
+ type: modal
+ extensionType: codedComponents
+ description: |
+ Quick pick UI for user selection. Native VS Code component
+ rendered by the editor, controlled via Extension API.
+ supportedComponents:
+ - quickPick
+ constraints:
+ searchable: true
+ multiSelect: true
+ context:
+ provides:
+ - workspace
+ actions:
+ - show
+ - hide
+ - dispose
+ extensionTypeConfig:
+ sdk: vscode-api
+
+ - id: input-box
+ name: Input Box
+ type: modal
+ extensionType: codedComponents
+ description: |
+ Input box for text entry. Native VS Code component.
+ supportedComponents:
+ - inputBox
+ constraints:
+ validation: true
+ context:
+ provides:
+ - workspace
+ extensionTypeConfig:
+ sdk: vscode-api
+
+renderingEngines:
+ webview-iframe:
+ type: custom
+ name: Webview (HTML + CSS + JS in Iframe)
+ description: |
+ Webviews run custom HTML/CSS/JavaScript in sandboxed iframes.
+ Developers can use Webview UI Toolkit, React, Vue, or any framework.
+ Communication with Extension Host via postMessage.
+ sandboxing:
+ iframeSandbox: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ cspPolicy: "default-src 'none'; style-src ${webview.cspSource} 'unsafe-inline'; script-src 'nonce-${nonce}'"
+ platforms:
+ - VS Code Desktop (Windows, macOS, Linux)
+ - VS Code Web (browser)
+
+ native-vscode:
+ type: custom
+ name: Native VS Code Components
+ description: |
+ Tree views, status bar items, quick picks, and other native UI
+ elements are rendered by VS Code itself. Extensions provide data
+ and behavior via the Extension API.
+ platforms:
+ - VS Code Desktop (Windows, macOS, Linux)
+ - VS Code Web (browser)
+
+architecture:
+ executionModel: dual-process
+ description: |
+ VS Code extensions use a dual-process architecture:
+
+ 1. Extension Host (Node.js): Runs extension code with access to VS Code API
+ - Full VS Code API access (vscode.*)
+ - File system access, Node.js capabilities
+ - Can open webviews and create UI elements
+ - No direct DOM access to editor
+
+ 2. Webview (Sandboxed Iframe): Custom HTML/CSS/JS for rich UI
+ - Full DOM access for custom rendering
+ - No direct VS Code API access
+ - Communicates with Extension Host via postMessage
+ - Uses acquireVsCodeApi() for message passing
+
+ This separation ensures security while allowing rich custom UIs.
+
+ communication:
+ protocol: postMessage
+ description: |
+ Extension Host and Webview communicate via window.postMessage API.
+
+ Extension Host -> Webview: webview.postMessage(data)
+ Webview -> Extension Host: vscode.postMessage(data)
+
+ Extension Host listens: webview.onDidReceiveMessage(msg => { ... })
+ Webview listens: window.addEventListener('message', event => { ... })
+
+ Webview gets API handle: const vscode = acquireVsCodeApi()
+
+extensionType: codedComponents
+
+jsonFormsIntegration:
+ supported: true
+ rendererSet: custom
+ customRenderersAllowed: true
+ notes: |
+ Developers can integrate JSON Forms in webviews with custom renderers
+ using Webview UI Toolkit or other frameworks.
+
+mcpAppsIntegration:
+ supported: false
+ notes: |
+ Not currently integrated with MCP Apps specification, but webview
+ architecture could potentially support MCP Apps UI resources.
+
+extensions:
+ compliance:
+ marketplaceReview:
+ required: true
+ scope: publicExtensions
+ description: |
+ All public marketplace extensions undergo review:
+ 1. Automated security scanning
+ 2. Malware detection
+ 3. Code analysis for suspicious patterns
+ 4. Manual review for quality and functionality
+ 5. Verification of description accuracy
+ timeline: "Typically 1-3 business days"
+ documentation: https://code.visualstudio.com/api/working-with-extensions/publishing-extension#review-extension-submission
+
+ securityRequirements:
+ - name: Content Security Policy
+ description: Webviews must use restrictive CSP
+ required: true
+ - name: Sandboxing
+ description: Webviews run in sandboxed iframes
+ required: true
+ - name: API Access
+ description: Only access VS Code API from Extension Host
+ required: true
+ - name: Data Privacy
+ description: No unauthorized telemetry or data collection
+ required: true
+ - name: Sensitive Data
+ description: Secure handling of credentials and tokens
+ required: true
+
+ securityGuidelines:
+ url: https://code.visualstudio.com/api/extension-guides/webview#security
+ requirements:
+ - Use Content Security Policy in all webviews
+ - Sanitize user input to prevent XSS
+ - Use nonces for inline scripts
+ - Validate messages from webviews
+ - Store secrets securely using VS Code's SecretStorage API
+ - Disable insecure content in webviews
+ - Follow principle of least privilege
+
+ accessibility:
+ platformStandard: "WCAG 2.1 AA"
+ requirements:
+ - Keyboard navigation support
+ - Screen reader compatibility
+ - High contrast theme support
+ - Focus indicators
+ - Semantic HTML in webviews
+ - ARIA labels where needed
+ documentation: https://code.visualstudio.com/api/extension-guides/accessibility
+
+ manifest:
+ file: package.json
+ description: |
+ Every extension requires a package.json manifest defining:
+ - Extension metadata (name, version, publisher, description)
+ - Activation events (when extension loads)
+ - Contribution points (commands, views, languages, etc.)
+ - Dependencies and engines
+ - Extension capabilities and permissions
+ schema:
+ name:
+ type: string
+ required: true
+ description: Extension name (lowercase, no spaces)
+ displayName:
+ type: string
+ required: true
+ description: Human-readable display name
+ version:
+ type: string
+ required: true
+ description: Semantic version
+ publisher:
+ type: string
+ required: true
+ description: Publisher identifier
+ engines:
+ type: object
+ required: true
+ description: VS Code version compatibility
+ activationEvents:
+ type: array
+ required: false
+ description: Events that trigger extension activation
+ main:
+ type: string
+ required: false
+ description: Entry point for Extension Host code
+ contributes:
+ type: object
+ required: false
+ description: Contribution points (commands, views, etc.)
+ categories:
+ type: array
+ required: false
+ description: Extension categories for marketplace
+ icon:
+ type: string
+ required: false
+ description: Path to extension icon
+
+ developmentTools:
+ - name: Extension Generator
+ description: Yeoman generator for scaffolding extensions
+ package: "generator-code"
+ command: "yo code"
+ url: https://github.com/microsoft/vscode-generator-code
+
+ - name: vsce (Publishing Tool)
+ description: CLI for packaging and publishing extensions
+ package: "@vscode/vsce"
+ command: "vsce package / vsce publish"
+ url: https://github.com/microsoft/vscode-vsce
+
+ - name: Extension Test Runner
+ description: Test framework for extensions
+ package: "@vscode/test-electron"
+ url: https://github.com/microsoft/vscode-test
+
+ - name: Webview UI Toolkit Samples
+ description: Sample code and documentation
+ url: https://github.com/microsoft/vscode-webview-ui-toolkit-samples
+
+ - name: Extension Samples Repository
+ description: Official extension samples
+ url: https://github.com/microsoft/vscode-extension-samples
+
+ theming:
+ enabled: true
+ description: |
+ VS Code supports multiple color themes (light, dark, high contrast).
+ Extensions should respect the active theme.
+ implementation:
+ webviewSupport: true
+ cssVariables: true
+ themingApi: true
+ colorThemes:
+ - Light (Visual Studio)
+ - Dark (Visual Studio Dark)
+ - High Contrast Light
+ - High Contrast Dark
+ guidelines:
+ - Use CSS variables for theming in webviews
+ - Support all theme types
+ - Use theme colors from VS Code API
+ - Test in all theme modes
+
+notes: |
+ Visual Studio Code's Extension Platform provides a sophisticated dual-process
+ architecture that balances security, performance, and flexibility.
+
+ Key characteristics:
+ - Extension Host: Node.js process for extension logic with full VS Code API
+ - Webview: Sandboxed iframe for custom UI with HTML/CSS/JS
+ - Communication: postMessage for Extension Host <-> Webview communication
+ - Webview UI Toolkit: Optional but recommended for consistent, themed UI
+ - Native Components: Tree views, status bar, quick picks rendered by VS Code
+ - Contribution Points: Extensive customization via package.json
+ - Security: Sandboxed webviews, CSP enforcement, marketplace review
+
+ The architecture allows rich custom UIs while maintaining editor security and
+ performance. Extensions can choose between native VS Code components (tree views,
+ status bar) or fully custom webview UIs.
+
+metadata:
+ fenestra:
+ createdAt: "2025-12-30"
+ author: "Fenestra Specification Team"
+ category: "Development Tools"
+ tags:
+ - code-editor
+ - ide
+ - extensions
+ - webview
+ - desktop-app
+ relatedPlatforms:
+ - JetBrains IDE Plugins
+ - Eclipse Plugins
+ - Atom Packages
+ - Sublime Text Packages
diff --git a/specs/fenestra/examples/0.1.0/zendesk.fenestra.yaml b/specs/fenestra/examples/0.1.0/zendesk.fenestra.yaml
new file mode 100644
index 0000000..fb91834
--- /dev/null
+++ b/specs/fenestra/examples/0.1.0/zendesk.fenestra.yaml
@@ -0,0 +1,1298 @@
+# Fenestra Document: Zendesk Apps Framework
+#
+# Zendesk Apps Framework represents iframe-based apps with recommended
+# component library. Apps run in sandboxed iframes and communicate via
+# ZAFClient. Garden Design System (React) is strongly recommended.
+
+fenestra: "0.1.0"
+
+info:
+ title: Zendesk Apps Framework UI Ecosystem
+ version: "1.0.0"
+ description: |
+ Zendesk Apps Framework (ZAF) enables developers to extend Zendesk products
+ with custom apps running in sandboxed iframes. Apps communicate with the
+ host Zendesk product via the ZAFClient SDK for cross-frame messaging.
+
+ Key characteristic: Apps run in iframes with ZAFClient REQUIRED for platform
+ communication. Garden Design System (React components) is RECOMMENDED for
+ consistent UI but not enforced. Developers can use their own components.
+
+ contact:
+ name: Zendesk Developer Relations
+ url: https://developer.zendesk.com/
+ email: developers@zendesk.com
+
+platform:
+ name: Zendesk
+ vendor: Zendesk, Inc.
+ documentation: https://developer.zendesk.com/documentation/apps/
+ appMarketplace: https://www.zendesk.com/marketplace/
+ developerPortal: https://apps.zendesk.com/
+ changelog: https://developer.zendesk.com/documentation/apps/changelog/
+
+sdks:
+ zaf-sdk:
+ name: Zendesk Apps Framework SDK
+ packageManager: npm
+ package: "zendesk_app_framework_sdk"
+ version: "^2.0.0"
+ repository: https://github.com/zendesk/zendesk_app_framework_sdk
+ documentation: https://developer.zendesk.com/api-reference/apps/apps-core-api/client_api/
+ cdn: https://static.zdassets.com/zendesk_app_framework_sdk/2.0/zaf_sdk.min.js
+ description: |
+ The ZAF SDK provides the ZAFClient for cross-frame communication between
+ your iframe app and the host Zendesk product. Enables event listening,
+ property access, and action invocation on the Zendesk platform.
+ exports:
+ ZAFClient:
+ type: class
+ description: |
+ Main client for communicating with Zendesk Apps Framework.
+ Initialize with ZAFClient.init() to establish connection.
+ init:
+ type: method
+ description: |
+ Initializes connection between app and ZAF platform. Returns
+ client instance for ongoing communication. Triggers app.registered
+ event when connection is established.
+ get:
+ type: method
+ description: Retrieves data from the Zendesk platform (ticket, user, context)
+ set:
+ type: method
+ description: Sets data on the Zendesk platform
+ invoke:
+ type: method
+ description: Invokes actions on the Zendesk platform (resize, modal, notify)
+ on:
+ type: method
+ description: Registers event listeners for platform events
+ request:
+ type: method
+ description: Makes HTTP requests with authentication handled by ZAF
+ metadata:
+ type: method
+ description: Retrieves app metadata and settings
+ context:
+ type: method
+ description: Gets current context (location, instanceGuid, account)
+
+ garden-react:
+ name: Zendesk Garden React Components
+ packageManager: npm
+ package: "@zendeskgarden/react-components"
+ version: "^9.0.0"
+ repository: https://github.com/zendeskgarden/react-components
+ documentation: https://garden.zendesk.com/components/
+ description: |
+ Garden is Zendesk's design system providing React components for
+ building consistent, accessible UIs. Components are published as
+ individual packages but can be used together seamlessly.
+ exports:
+ # Action Components
+ Button:
+ type: component
+ description: Primary action button with variants
+ package: "@zendeskgarden/react-buttons"
+ IconButton:
+ type: component
+ description: Button with icon only
+ package: "@zendeskgarden/react-buttons"
+ Anchor:
+ type: component
+ description: Styled link component
+ package: "@zendeskgarden/react-buttons"
+
+ # Form Components
+ Input:
+ type: component
+ description: Text input field
+ package: "@zendeskgarden/react-forms"
+ Textarea:
+ type: component
+ description: Multi-line text input
+ package: "@zendeskgarden/react-forms"
+ Checkbox:
+ type: component
+ description: Checkbox input
+ package: "@zendeskgarden/react-forms"
+ Radio:
+ type: component
+ description: Radio button input
+ package: "@zendeskgarden/react-forms"
+ Toggle:
+ type: component
+ description: Toggle switch
+ package: "@zendeskgarden/react-forms"
+ Field:
+ type: component
+ description: Form field container with label and hint
+ package: "@zendeskgarden/react-forms"
+
+ # Dropdown Components
+ Select:
+ type: component
+ description: Select dropdown (non-editable)
+ package: "@zendeskgarden/react-dropdowns"
+ Combobox:
+ type: component
+ description: Editable dropdown with autocomplete
+ package: "@zendeskgarden/react-dropdowns"
+ Menu:
+ type: component
+ description: Dropdown menu with items
+ package: "@zendeskgarden/react-dropdowns"
+ Autocomplete:
+ type: component
+ description: Autocomplete input
+ package: "@zendeskgarden/react-dropdowns"
+
+ # Chrome Components (Layout)
+ Chrome:
+ type: component
+ description: Main application shell container
+ package: "@zendeskgarden/react-chrome"
+ Header:
+ type: component
+ description: Application header
+ package: "@zendeskgarden/react-chrome"
+ Nav:
+ type: component
+ description: Navigation container
+ package: "@zendeskgarden/react-chrome"
+ Body:
+ type: component
+ description: Main content body
+ package: "@zendeskgarden/react-chrome"
+ Footer:
+ type: component
+ description: Application footer
+ package: "@zendeskgarden/react-chrome"
+
+ # Modal Components
+ Modal:
+ type: component
+ description: Modal dialog overlay
+ package: "@zendeskgarden/react-modals"
+ Drawer:
+ type: component
+ description: Slide-in drawer panel
+ package: "@zendeskgarden/react-modals"
+ TooltipModal:
+ type: component
+ description: Tooltip-style modal
+ package: "@zendeskgarden/react-modals"
+
+ # Navigation Components
+ Tabs:
+ type: component
+ description: Tab navigation component
+ package: "@zendeskgarden/react-tabs"
+ Accordion:
+ type: component
+ description: Expandable/collapsible sections
+ package: "@zendeskgarden/react-accordions"
+
+ # Notification Components
+ Notification:
+ type: component
+ description: Toast/banner notification
+ package: "@zendeskgarden/react-notifications"
+ Alert:
+ type: component
+ description: Alert message component
+ package: "@zendeskgarden/react-notifications"
+ Well:
+ type: component
+ description: Highlighted content container
+ package: "@zendeskgarden/react-notifications"
+
+ # Data Display
+ Table:
+ type: component
+ description: Data table with sorting and selection
+ package: "@zendeskgarden/react-tables"
+ Avatar:
+ type: component
+ description: User avatar component
+ package: "@zendeskgarden/react-avatars"
+ Tag:
+ type: component
+ description: Tag/label component
+ package: "@zendeskgarden/react-tags"
+ Tooltip:
+ type: component
+ description: Tooltip overlay
+ package: "@zendeskgarden/react-tooltips"
+
+ # Layout Components
+ Grid:
+ type: component
+ description: Responsive grid system
+ package: "@zendeskgarden/react-grid"
+ Pagination:
+ type: component
+ description: Pagination controls
+ package: "@zendeskgarden/react-pagination"
+
+ # Loaders
+ Spinner:
+ type: component
+ description: Loading spinner
+ package: "@zendeskgarden/react-loaders"
+ Skeleton:
+ type: component
+ description: Skeleton placeholder
+ package: "@zendeskgarden/react-loaders"
+ Dots:
+ type: component
+ description: Dots loading indicator
+ package: "@zendeskgarden/react-loaders"
+
+componentCatalog:
+ categories:
+ action:
+ name: Actions
+ description: Interactive elements for user actions
+ components: [button, iconButton, anchor]
+
+ input:
+ name: Form Inputs
+ description: Form controls for user input
+ components: [input, textarea, checkbox, radio, toggle, field]
+
+ dropdown:
+ name: Dropdowns
+ description: Dropdown menus and select components
+ components: [select, combobox, menu, autocomplete]
+
+ chrome:
+ name: Chrome (Layout)
+ description: Application shell and layout components
+ components: [chrome, header, nav, body, footer]
+
+ overlay:
+ name: Overlays
+ description: Modal dialogs and overlays
+ components: [modal, drawer, tooltipModal, tooltip]
+
+ navigation:
+ name: Navigation
+ description: Navigation and organization components
+ components: [tabs, accordion]
+
+ notification:
+ name: Notifications
+ description: Alert and notification components
+ components: [notification, alert, well]
+
+ dataDisplay:
+ name: Data Display
+ description: Components for displaying data
+ components: [table, avatar, tag]
+
+ layout:
+ name: Layout
+ description: Grid and layout utilities
+ components: [grid, pagination]
+
+ feedback:
+ name: Feedback
+ description: Loading and progress indicators
+ components: [spinner, skeleton, dots]
+
+ components:
+ # ACTION COMPONENTS
+ button:
+ name: Button
+ description: |
+ Primary action button with multiple variants and sizes.
+ Supports default, primary, and basic types with optional danger styling.
+ category: action
+ sdkBinding:
+ sdk: garden-react
+ export: Button
+ package: "@zendeskgarden/react-buttons"
+ webStandardMapping:
+ htmlElement: button
+ ariaRole: button
+ semanticType: action
+ props:
+ size:
+ type: string
+ enum: [small, medium, large]
+ default: medium
+ description: Button size
+ isPrimary:
+ type: boolean
+ default: false
+ description: Primary button style (blue)
+ isBasic:
+ type: boolean
+ default: false
+ description: Basic button style (minimal)
+ isDanger:
+ type: boolean
+ default: false
+ description: Danger styling for destructive actions
+ isStretched:
+ type: boolean
+ default: false
+ description: Stretch to fill container width
+ disabled:
+ type: boolean
+ default: false
+ description: Disable the button
+ focusInset:
+ type: boolean
+ default: false
+ description: Inset focus indicator
+ variants:
+ - default
+ - primary
+ - basic
+ - danger
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ labelRequired: true
+ examples:
+ - title: Primary Button
+ code: |
+ import { Button } from '@zendeskgarden/react-buttons';
+
+
+ language: jsx
+ - title: Danger Button
+ code: |
+ import { Button } from '@zendeskgarden/react-buttons';
+
+
+ language: jsx
+
+ modal:
+ name: Modal
+ description: |
+ Modal dialog that overlays the page and blocks interaction with
+ the rest of the content. Available in default and large sizes.
+ category: overlay
+ sdkBinding:
+ sdk: garden-react
+ export: Modal
+ package: "@zendeskgarden/react-modals"
+ webStandardMapping:
+ htmlElement: dialog
+ ariaRole: dialog
+ semanticType: container
+ props:
+ isLarge:
+ type: boolean
+ default: false
+ description: Large modal size
+ focusOnMount:
+ type: boolean
+ default: true
+ description: Focus modal on mount
+ backdropProps:
+ type: object
+ description: Props for the backdrop element
+ onClose:
+ type: function
+ description: Callback when modal is closed
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ focusTrap: true
+ escapeToClose: true
+ examples:
+ - title: Basic Modal
+ code: |
+ import { Modal, Header, Body, Footer, Close } from '@zendeskgarden/react-modals';
+ import { Button } from '@zendeskgarden/react-buttons';
+
+ setIsOpen(false)}>
+
+ Modal content goes here
+
+
+
+ language: jsx
+
+ input:
+ name: Input
+ description: |
+ Text input field for user data entry. Should be nested within
+ a Field component for proper accessibility attributes.
+ category: input
+ sdkBinding:
+ sdk: garden-react
+ export: Input
+ package: "@zendeskgarden/react-forms"
+ webStandardMapping:
+ htmlElement: input
+ inputType: text
+ semanticType: input
+ props:
+ isCompact:
+ type: boolean
+ default: false
+ description: Compact sizing
+ isBare:
+ type: boolean
+ default: false
+ description: Remove borders and padding
+ focusInset:
+ type: boolean
+ default: false
+ description: Inset focus indicator
+ validation:
+ type: string
+ enum: [success, warning, error]
+ description: Validation state
+ accessibility:
+ labelRequired: true
+ keyboardSupport: true
+ screenReaderSupport: true
+ examples:
+ - title: Input with Label
+ code: |
+ import { Field, Label, Input, Hint } from '@zendeskgarden/react-forms';
+
+
+
+ Enter your email
+
+
+ language: jsx
+
+ select:
+ name: Select
+ description: |
+ Non-editable dropdown select component. Use isMultiselectable
+ for multiple selections. For editable dropdowns, use Combobox.
+ category: dropdown
+ sdkBinding:
+ sdk: garden-react
+ export: Select
+ package: "@zendeskgarden/react-dropdowns"
+ webStandardMapping:
+ htmlElement: select
+ ariaRole: listbox
+ semanticType: input
+ props:
+ isMultiselectable:
+ type: boolean
+ default: false
+ description: Allow multiple selections
+ isCompact:
+ type: boolean
+ default: false
+ description: Compact sizing
+ disabled:
+ type: boolean
+ default: false
+ placeholder:
+ type: string
+ description: Placeholder text
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ labelRequired: true
+
+ chrome:
+ name: Chrome
+ description: |
+ Main application shell container that provides consistent layout
+ structure for Zendesk-style applications.
+ category: chrome
+ sdkBinding:
+ sdk: garden-react
+ export: Chrome
+ package: "@zendeskgarden/react-chrome"
+ webStandardMapping:
+ htmlElement: div
+ semanticType: container
+ props:
+ isFluid:
+ type: boolean
+ default: false
+ description: Fluid width layout
+ hue:
+ type: string
+ description: Color hue for theming
+ examples:
+ - title: Basic Chrome Layout
+ code: |
+ import { Chrome, Header, Nav, Body, Footer } from '@zendeskgarden/react-chrome';
+
+
+
+
+ Main Content
+
+
+ language: jsx
+
+ table:
+ name: Table
+ description: |
+ Data table component with support for sorting, selection, and
+ row reordering (via dnd-kit). Available in small, medium, and large sizes.
+ category: dataDisplay
+ sdkBinding:
+ sdk: garden-react
+ export: Table
+ package: "@zendeskgarden/react-tables"
+ webStandardMapping:
+ htmlElement: table
+ ariaRole: table
+ semanticType: data
+ props:
+ size:
+ type: string
+ enum: [small, medium, large]
+ default: medium
+ description: Table row size
+ isReadOnly:
+ type: boolean
+ default: false
+ description: Read-only mode (no hover states)
+ accessibility:
+ keyboardSupport: true
+ screenReaderSupport: true
+ captionRecommended: true
+
+ notification:
+ name: Notification
+ description: |
+ Toast/banner notification for displaying messages to users.
+ Supports multiple types (success, warning, error, info).
+ category: notification
+ sdkBinding:
+ sdk: garden-react
+ export: Notification
+ package: "@zendeskgarden/react-notifications"
+ props:
+ type:
+ type: string
+ enum: [success, warning, error, info]
+ description: Notification type
+ placement:
+ type: string
+ enum: [top-start, top, top-end, bottom-start, bottom, bottom-end]
+ description: Notification placement
+ accessibility:
+ ariaRole: status
+ screenReaderSupport: true
+
+policies:
+ componentRequirement:
+ level: recommended
+ scope: all
+ rationale: |
+ Zendesk strongly recommends using Garden Design System components for
+ consistent UI, accessibility, and integration with Zendesk products.
+ However, component usage is not enforced - developers can use their
+ own components or frameworks while still communicating via ZAFClient.
+
+ customComponents:
+ allowed: true
+ constraints:
+ - Apps must run in sandboxed iframe
+ - Must use ZAFClient SDK for platform communication
+ - Must respect iframe sandbox constraints
+ registrationRequired: false
+ approvalRequired: false
+ documentation: https://developer.zendesk.com/documentation/apps/app-developer-guide/using-the-apps-framework/
+ rationale: |
+ Apps have freedom to use any UI framework (React, Vue, Angular, vanilla JS)
+ as long as they communicate via ZAFClient and follow security guidelines.
+
+ publishing:
+ privateApps:
+ name: Private Apps
+ componentRequirement: recommended
+ customComponentsAllowed: true
+ reviewRequired: false
+ notes: |
+ Private apps for single Zendesk accounts. Garden recommended but
+ not required. No marketplace review needed.
+
+ publicApps:
+ name: Public Apps
+ componentRequirement: recommended
+ customComponentsAllowed: true
+ reviewRequired: true
+ securityReviewRequired: true
+ notes: |
+ Apps distributed to multiple customers must be submitted to Marketplace
+ for security and compliance review. Must use global OAuth for auth.
+ requirements:
+ - Global OAuth authentication required
+ - Custom API headers required (X-Zendesk-Marketplace-*)
+ - Security review for data handling
+ - Privacy policy disclosure required
+
+ marketplaceApps:
+ name: Marketplace Apps
+ componentRequirement: recommended
+ customComponentsAllowed: true
+ certificationRequired: false
+ reviewRequired: true
+ securityReviewRequired: true
+ notes: |
+ Apps listed in Zendesk Marketplace undergo comprehensive review
+ including security, functionality, and compliance verification.
+ requirements:
+ - Must include X-Zendesk-Marketplace-Name header
+ - Must include X-Zendesk-Marketplace-Organization-Id header
+ - Must include X-Zendesk-Marketplace-App-Id header
+ - Data handling disclosure required
+ - Privacy policy and terms of service required
+ - OAuth scope audit
+ - API security verification
+
+ designGuidelines:
+ required: false
+ designSystem: "Zendesk Garden"
+ designSystemUrl: https://garden.zendesk.com/
+ designTokensProvided: true
+ guidelines:
+ - Use Garden components for consistent UI (recommended)
+ - Follow accessibility best practices (WCAG 2.1 AA)
+ - Provide clear labels and helper text
+ - Use validation states appropriately
+ - Ensure keyboard navigation support
+ - Test in different iframe contexts
+
+ security:
+ iframeSandbox: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ - allow-same-origin
+ - allow-popups
+ secureSettings:
+ enabled: true
+ description: |
+ Use secure settings for sensitive data like API tokens or passwords.
+ Secure settings are encrypted and cannot be read by the app - they
+ can only be used as placeholders replaced by the server.
+ domainWhitelist: required
+ authentication:
+ globalOAuth: required
+ apiTokens: prohibited
+ notes: |
+ Public apps must use global OAuth access tokens. API tokens or
+ regular OAuth tokens are prohibited per Zendesk Developer Terms.
+
+extensionPoints:
+ - id: ticket-sidebar
+ name: Ticket Sidebar
+ type: panel
+ extensionType: iframe
+ description: |
+ Panel on the right side of the ticket in the agent interface.
+ Primary location for ticket-related app functionality.
+ supportedComponents:
+ - all
+ constraints:
+ defaultWidth: 320
+ flexible: true
+ autoLoad: optional
+ autoHide: optional
+ configuration:
+ flexible:
+ type: boolean
+ default: true
+ description: |
+ If true, iframe automatically resizes to match app tray width.
+ If false, iframe stays fixed at 320px width.
+ autoLoad:
+ type: boolean
+ default: true
+ description: Automatically load app when ticket opens
+ autoHide:
+ type: boolean
+ default: false
+ description: Hide app by default until clicked
+ context:
+ provides:
+ - ticket
+ - user
+ - currentUser
+ - organization
+ - group
+ - locale
+ - instances
+ actions:
+ - resize
+ - invoke
+ - get
+ - set
+ - request
+ - notify
+ events:
+ - ticket.save
+ - ticket.updated
+ - ticket.submit.start
+ - ticket.submit.done
+ - app.activated
+ - app.deactivated
+ - app.registered
+ documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/ticket_sidebar/
+
+ - id: new-ticket-sidebar
+ name: New Ticket Sidebar
+ type: panel
+ extensionType: iframe
+ description: |
+ Panel on the right side of the new ticket interface. Similar to
+ ticket sidebar but for new ticket creation flow.
+ supportedComponents:
+ - all
+ constraints:
+ defaultWidth: 320
+ flexible: true
+ autoLoad: optional
+ context:
+ provides:
+ - ticket
+ - user
+ - currentUser
+ - locale
+ actions:
+ - resize
+ - invoke
+ - get
+ - set
+ documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/ticket_sidebar/
+
+ - id: nav-bar
+ name: Navigation Bar
+ type: panel
+ extensionType: iframe
+ description: |
+ Icon in the left navigation bar. Opens a modal or panel when clicked.
+ Good for app functionality not tied to specific tickets.
+ supportedComponents:
+ - all
+ constraints:
+ iconRequired: true
+ responsive: true
+ configuration:
+ icon:
+ type: string
+ required: true
+ description: Icon to display in nav bar
+ url:
+ type: string
+ description: URL to load in iframe
+ context:
+ provides:
+ - currentUser
+ - locale
+ - instances
+ actions:
+ - resize
+ - invoke
+ - get
+ - request
+ documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/nav_bar/
+
+ - id: top-bar
+ name: Top Bar
+ type: panel
+ extensionType: iframe
+ description: |
+ Panel in the top bar of the agent interface. Can be always visible
+ or triggered by an icon. Supports custom sizing.
+ supportedComponents:
+ - all
+ constraints:
+ maxWidth: 600
+ maxHeight: 600
+ responsive: true
+ autoHide: optional
+ configuration:
+ autoHide:
+ type: boolean
+ default: false
+ description: Hide by default, show on icon click
+ url:
+ type: string
+ description: URL to load in iframe
+ size:
+ type: object
+ properties:
+ width:
+ type: string
+ description: Width in px or %
+ height:
+ type: string
+ description: Height in px or %
+ context:
+ provides:
+ - currentUser
+ - locale
+ - instances
+ actions:
+ - resize
+ - invoke
+ - get
+ documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/top_bar/
+
+ - id: modal
+ name: Modal Dialog
+ type: modal
+ extensionType: iframe
+ description: |
+ Modal overlay opened programmatically via client.invoke('instances.create').
+ Good for focused tasks or data collection workflows.
+ supportedComponents:
+ - all
+ constraints:
+ maxWidth: 800
+ maxHeight: 600
+ responsive: true
+ configuration:
+ url:
+ type: string
+ description: URL to load in modal iframe
+ size:
+ type: object
+ properties:
+ width:
+ type: string
+ height:
+ type: string
+ context:
+ provides:
+ - context
+ - currentUser
+ - locale
+ actions:
+ - close
+ - resize
+ - get
+ - invoke
+ invocation:
+ method: client.invoke('instances.create')
+ parameters:
+ location: modal
+ url: string
+ size: object
+ documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/modal/
+
+ - id: background
+ name: Background
+ type: service
+ extensionType: iframe
+ description: |
+ Background app with no UI. Runs invisibly to handle events and
+ perform server-side operations. Useful for webhooks and automation.
+ supportedComponents:
+ - none (no UI)
+ constraints:
+ noUI: true
+ eventsOnly: true
+ context:
+ provides:
+ - currentUser
+ - locale
+ - account
+ actions:
+ - get
+ - request
+ - invoke
+ events:
+ - ticket.save
+ - ticket.updated
+ - app.activated
+ - app.registered
+ notes: |
+ Background apps don't have a visible UI. They respond to platform
+ events like ticket.save (server-side completion) and can perform
+ automated actions or integrations.
+ documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/background/
+
+ - id: organization-sidebar
+ name: Organization Sidebar
+ type: panel
+ extensionType: iframe
+ description: |
+ Panel on the organization page, similar to ticket sidebar but
+ for organization-related functionality.
+ supportedComponents:
+ - all
+ constraints:
+ defaultWidth: 320
+ flexible: true
+ context:
+ provides:
+ - organization
+ - currentUser
+ - locale
+ actions:
+ - resize
+ - get
+ - invoke
+ documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/organization_sidebar/
+
+ - id: user-sidebar
+ name: User Sidebar
+ type: panel
+ extensionType: iframe
+ description: |
+ Panel on the user profile page for user-specific app features.
+ supportedComponents:
+ - all
+ constraints:
+ defaultWidth: 320
+ flexible: true
+ context:
+ provides:
+ - user
+ - currentUser
+ - locale
+ actions:
+ - resize
+ - get
+ - invoke
+ documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/user_sidebar/
+
+renderingEngines:
+ iframe-sandbox:
+ type: custom
+ name: Sandboxed IFrame
+ description: |
+ Apps run in sandboxed iframes with restricted permissions.
+ Communication with the host Zendesk product happens via ZAFClient
+ using secure cross-frame messaging (postMessage).
+ sandboxing:
+ iframeSandbox: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ - allow-same-origin
+ - allow-popups
+ crossFrameMessaging: postMessage
+ securityModel: |
+ Apps are isolated in iframes and can only interact with Zendesk
+ via the ZAFClient SDK. This ensures security and prevents direct
+ DOM access to the host application.
+
+ any-framework:
+ type: custom
+ name: Any JavaScript Framework
+ description: |
+ Developers can use any frontend framework (React, Vue, Angular,
+ Svelte, vanilla JS) inside the iframe as long as they integrate
+ with ZAFClient for platform communication.
+ frameworks:
+ - React (recommended with Garden)
+ - Vue
+ - Angular
+ - Svelte
+ - Vanilla JavaScript
+ - Any framework that can run in a browser iframe
+
+jsonFormsIntegration:
+ supported: true
+ rendererSet: custom
+ customRenderersAllowed: true
+ notes: |
+ Developers can integrate JSON Forms with Garden component renderers
+ or custom renderers within their iframe apps.
+
+mcpAppsIntegration:
+ supported: false
+ notes: "Potential future integration via iframe embedding"
+
+extensionType: iframe
+
+extensions:
+ i18n:
+ enabled: true
+ localeDetection: automatic
+ description: |
+ Zendesk Apps Framework provides automatic locale detection via
+ ZAFClient. Apps can localize content using translation JSON files
+ in the translations folder with data-i18n-key attributes.
+ implementation:
+ translationFiles:
+ location: translations/
+ format: json
+ naming: "{locale}.json"
+ example: |
+ translations/en.json:
+ { "default": { "hello_world": "Hello World!" }}
+
+ translations/fr.json:
+ { "default": { "hello_world": "Bonjour le Monde!" }}
+ htmlIntegration:
+ attribute: data-i18n-key
+ description: |
+ Add data-i18n-key attribute to HTML elements. The framework
+ replaces element text with the corresponding translation string
+ based on user locale.
+ example:
+ fallbackBehavior:
+ defaultLocale: en
+ description: Falls back to English if user locale not available
+ clientProvides:
+ - currentUser.locale
+ - currentAccount.locale
+ developerResponsibility:
+ - Create translation files for supported locales
+ - Add data-i18n-key attributes to HTML elements
+ - Handle locale-specific date/time formatting
+ - Support RTL languages if needed
+ supportedLocales:
+ - en-US (English - United States)
+ - en-GB (English - United Kingdom)
+ - de (German)
+ - es (Spanish)
+ - es-419 (Spanish - Latin America)
+ - fr (French)
+ - fr-ca (French - Canada)
+ - it (Italian)
+ - ja (Japanese)
+ - ko (Korean)
+ - nl (Dutch)
+ - pl (Polish)
+ - pt-br (Portuguese - Brazil)
+ - pt (Portuguese)
+ - ru (Russian)
+ - sv (Swedish)
+ - tr (Turkish)
+ - zh-cn (Chinese - Simplified)
+ - zh-tw (Chinese - Traditional)
+ - da (Danish)
+ - fi (Finnish)
+ - no (Norwegian)
+ - cs (Czech)
+ - id (Indonesian)
+ - th (Thai)
+ - ar (Arabic)
+ - he (Hebrew)
+ documentation: https://developer.zendesk.com/documentation/apps/build-an-app/localizing-a-support-app/
+
+ compliance:
+ enabled: true
+ description: |
+ Apps distributed to multiple Zendesk customers must comply with
+ Marketplace security requirements, data handling policies, and
+ authentication standards.
+ requirements:
+ securityReview:
+ required: true
+ scope: publicDistribution
+ includes:
+ - Data handling and privacy review
+ - OAuth implementation verification
+ - Secure API usage patterns
+ - Permission scope audit
+ - Custom header verification
+ documentation: https://developer.zendesk.com/documentation/marketplace/
+ functionalReview:
+ required: true
+ scope: marketplaceApps
+ includes:
+ - App functionality testing
+ - Error handling validation
+ - User experience assessment
+ - Performance testing
+ contentReview:
+ required: true
+ scope: marketplaceApps
+ includes:
+ - App listing content accuracy
+ - Screenshots and media quality
+ - Privacy policy completeness
+ - Terms of service clarity
+ authenticationRequirements:
+ globalOAuth: required
+ apiTokens: prohibited
+ scope: publicApps
+ description: |
+ Public apps must use global OAuth access tokens. API tokens
+ and regular OAuth tokens are prohibited for apps distributed
+ to multiple customers.
+ documentation: https://developer.zendesk.com/api-reference/introduction/security-and-auth/
+ apiHeaderRequirements:
+ required: true
+ scope: marketplaceApps
+ headers:
+ X-Zendesk-Marketplace-Name:
+ required: true
+ description: Name of the integration (can change)
+ X-Zendesk-Marketplace-Organization-Id:
+ required: true
+ description: Organization ID from developer portal (static)
+ X-Zendesk-Marketplace-App-Id:
+ required: true
+ description: App ID assigned when submitted
+ notes: |
+ Custom headers verified during submission process. Required for
+ all external API requests from marketplace apps.
+ documentation: https://developer.zendesk.com/documentation/marketplace/building-a-marketplace-app/request-header-requirements-for-marketplace-apps/
+ dataHandling:
+ disclosureRequired: true
+ description: |
+ Apps must disclose what Zendesk data they access and for what
+ purpose. Must follow data protection and privacy regulations.
+ constraints:
+ - No unauthorized data sharing
+ - Secure data storage
+ - Compliance with GDPR, CCPA, etc.
+ - Customer data isolation
+ secureSettings:
+ enabled: true
+ description: |
+ Use secure settings in manifest.json for sensitive data.
+ Secure settings are encrypted and can only be used as
+ server-side placeholders, not read by client code.
+ domainWhitelist: required
+ bestPractices:
+ - Never expose API tokens in client code
+ - Use secure settings with domainWhitelist
+ - Don't attempt to read secure settings (won't work)
+ certifications:
+ marketplaceListing:
+ available: true
+ description: Apps approved for Marketplace listing
+ securityCompliance:
+ available: true
+ description: Security and compliance verification
+ documentation: https://support.zendesk.com/hc/en-us/articles/9590471542170
+ guidelines: https://developer.zendesk.com/documentation/marketplace/building-a-marketplace-app/
+
+ analytics:
+ enabled: true
+ description: |
+ Zendesk provides analytics for marketplace apps including
+ installation metrics, usage data, and performance monitoring
+ through the developer portal.
+ metrics:
+ - Active installations
+ - User engagement
+ - API usage
+ - Error rates
+ - Performance metrics
+ dashboard: https://apps.zendesk.com/ (Developer Portal)
+
+ testing:
+ enabled: true
+ description: Tools and methods for testing Zendesk apps
+ tools:
+ zcli:
+ name: Zendesk CLI
+ description: Command-line tool for app development and testing
+ features:
+ - Local app server for development
+ - App packaging and validation
+ - App deployment to Zendesk instances
+ - Manifest validation
+ installation: npm install -g @zendesk/zcli
+ documentation: https://developer.zendesk.com/documentation/apps/getting-started/using-zcli/
+ localTesting:
+ description: |
+ Use ZCLI server to run app locally and test in Zendesk
+ products with live reloading and debugging.
+ command: zcli apps:server
+ validation:
+ manifestValidation: true
+ translationValidation: true
+ securityValidation: true
+ documentation: https://developer.zendesk.com/documentation/apps/app-developer-guide/build-and-test-your-app/
+
+ accessibilityFeatures:
+ keyboardNavigation: true
+ screenReaderSupport: true
+ highContrastMode: true
+ description: |
+ Garden components are built with accessibility in mind, following
+ WCAG 2.1 AA standards. Apps using Garden inherit these features.
+ guidelines:
+ - Use semantic HTML elements
+ - Provide ARIA labels where needed
+ - Ensure keyboard navigation works
+ - Test with screen readers
+ - Support high contrast modes
+ - Maintain adequate color contrast
+ - Provide focus indicators
+ documentation: https://garden.zendesk.com/components/
+
+ rateLimits:
+ description: Rate limits for Zendesk API requests
+ limits:
+ standard:
+ rate: 200 requests per minute per account
+ description: Standard API rate limit
+ concurrent:
+ rate: 5 concurrent requests per account
+ description: Maximum concurrent requests
+ search:
+ rate: 60 requests per minute
+ description: Search API specific limit
+ documentation: https://developer.zendesk.com/api-reference/introduction/rate-limits/
+
+ securityFeatures:
+ oauthRequired: true
+ scopedPermissions: true
+ iframeSandbox: true
+ description: |
+ Zendesk apps use OAuth for authentication with granular permission
+ scopes. Apps run in sandboxed iframes with controlled communication
+ via ZAFClient. Secure settings protect sensitive data.
+ features:
+ - OAuth 2.0 authentication
+ - Granular permission scopes
+ - Sandboxed iframe execution
+ - Secure settings encryption
+ - Domain whitelisting
+ - Request signing for marketplace apps
+ - HTTPS required for production
+ documentation: https://developer.zendesk.com/api-reference/introduction/security-and-auth/
+
+notes: |
+ Zendesk Apps Framework provides a flexible iframe-based extension model
+ where apps run in sandboxed iframes and communicate with the host Zendesk
+ product via the ZAFClient SDK.
+
+ Key characteristics:
+ - Iframe-based: Apps run in sandboxed iframes with controlled communication
+ - ZAFClient required: All platform interaction goes through ZAFClient SDK
+ - Garden recommended: Garden Design System strongly recommended but not enforced
+ - Framework agnostic: Use any frontend framework (React, Vue, Angular, etc.)
+ - Multiple locations: Apps can appear in sidebar, nav bar, top bar, modal, background
+ - Secure by default: OAuth, sandboxing, secure settings, domain whitelisting
+ - I18n support: Built-in locale detection and translation system
+ - Marketplace ready: Comprehensive review process for public apps
+
+ Apps have complete freedom in their UI implementation while maintaining
+ security through iframe sandboxing and ZAFClient communication protocol.
+ Garden components are strongly recommended for consistency with Zendesk UI
+ and built-in accessibility, but developers can choose their own approach.
+
+metadata:
+ fenestra:
+ createdAt: "2025-12-30"
+ author: "Fenestra Specification Team"
+ category: "Customer Service Platform"
+ tags:
+ - customer-service
+ - help-desk
+ - iframe
+ - react
+ - garden
+ - zaf
+ relatedPlatforms:
+ - Miro (iframe with optional components)
+ - Salesforce (Lightning Web Components)
+ - Intercom (iframe-based apps)
diff --git a/specs/fenestra/fenestra-spec.yaml b/specs/fenestra/fenestra-spec.yaml
new file mode 100644
index 0000000..31d7293
--- /dev/null
+++ b/specs/fenestra/fenestra-spec.yaml
@@ -0,0 +1,1536 @@
+# Fenestra Specification
+# Version: 0.1.0-draft
+#
+# A specification for describing platform UI component ecosystems, SDK bindings,
+# and UI rendering capabilities in a standardized, machine-readable format.
+#
+# Designed for submission to the OpenAPI Initiative (OAI), a Linux Foundation
+# Collaborative Project, to complement OpenAPI, Arazzo, and emerging specifications
+# like MCP Apps.
+
+openapi: 3.1.0
+info:
+ title: Fenestra Specification
+ version: 0.1.0-draft
+ description: |
+ # Fenestra Specification
+
+ **Fenestra** (Latin for "window") is a specification for describing how platforms
+ expose UI component ecosystems to developers building integrations, apps, and extensions.
+
+ ## Purpose
+
+ Modern platforms (HubSpot, Salesforce, Canva, Miro, Front, Slack, etc.) provide
+ UI extension points with varying degrees of flexibility. Fenestra standardizes
+ the description of:
+
+ 1. **Component Catalogs** - What UI components a platform provides
+ 2. **SDK Bindings** - How to import and use components from platform SDKs
+ 3. **Requirement Levels** - Whether platform components are required, recommended, or optional
+ 4. **Custom Component Policies** - Whether developers can bring their own components
+ 5. **Publishing Constraints** - Different rules for public vs private apps
+ 6. **Rendering Engines** - How UI definitions translate to rendered interfaces
+
+ ## Relationship to Other Specifications
+
+ - **OpenAPI**: Fenestra extends OpenAPI patterns for UI description
+ - **Arazzo**: Workflow sequences can reference Fenestra UI definitions for user interactions
+ - **MCP Apps**: Fenestra component definitions can map to MCP App UI resources
+ - **JSON Forms/JSON Schema**: Fenestra supports JSON Schema-based UI rendering
+
+ contact:
+ name: Fenestra Working Group
+ url: https://github.com/friggframework/fenestra-spec
+ license:
+ name: Apache 2.0
+ url: https://www.apache.org/licenses/LICENSE-2.0
+
+# =============================================================================
+# FENESTRA SPECIFICATION SCHEMA
+# =============================================================================
+
+components:
+ schemas:
+
+ # =========================================================================
+ # ROOT DOCUMENT
+ # =========================================================================
+
+ FenestraDocument:
+ type: object
+ required:
+ - fenestra
+ - info
+ properties:
+ fenestra:
+ type: string
+ description: Fenestra specification version
+ pattern: '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?$'
+ example: "0.1.0"
+
+ info:
+ $ref: '#/components/schemas/Info'
+
+ platform:
+ $ref: '#/components/schemas/Platform'
+
+ sdks:
+ type: object
+ description: SDK ecosystem definitions indexed by SDK identifier
+ additionalProperties:
+ $ref: '#/components/schemas/SDK'
+
+ componentCatalog:
+ $ref: '#/components/schemas/ComponentCatalog'
+
+ renderingEngines:
+ type: object
+ description: Supported rendering engine configurations
+ additionalProperties:
+ $ref: '#/components/schemas/RenderingEngine'
+
+ policies:
+ $ref: '#/components/schemas/Policies'
+
+ extensionPoints:
+ type: array
+ description: Where UI can be injected in the host platform
+ items:
+ $ref: '#/components/schemas/ExtensionPoint'
+
+ # =========================================================================
+ # INFO OBJECT
+ # =========================================================================
+
+ Info:
+ type: object
+ required:
+ - title
+ - version
+ properties:
+ title:
+ type: string
+ description: Human-readable name of this Fenestra document
+ version:
+ type: string
+ description: Version of this document
+ description:
+ type: string
+ description: Extended description (CommonMark supported)
+ termsOfService:
+ type: string
+ format: uri
+ contact:
+ type: object
+ properties:
+ name:
+ type: string
+ url:
+ type: string
+ format: uri
+ email:
+ type: string
+ format: email
+ license:
+ type: object
+ properties:
+ name:
+ type: string
+ url:
+ type: string
+ format: uri
+
+ # =========================================================================
+ # PLATFORM OBJECT
+ # =========================================================================
+
+ Platform:
+ type: object
+ description: |
+ Describes the host platform that provides the UI extension capabilities.
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ description: Platform name
+ examples:
+ - HubSpot
+ - Salesforce
+ - Canva
+ - Miro
+ - Front
+ - Slack
+
+ vendor:
+ type: string
+ description: Platform vendor/company name
+
+ documentation:
+ type: string
+ format: uri
+ description: URL to platform developer documentation
+
+ appMarketplace:
+ type: string
+ format: uri
+ description: URL to the platform's app marketplace/directory
+
+ # =========================================================================
+ # SDK OBJECT
+ # =========================================================================
+
+ SDK:
+ type: object
+ description: |
+ Describes an SDK package that provides UI components or utilities.
+ SDKs can be required, recommended, or optional depending on platform policies.
+ required:
+ - name
+ - packageManager
+ - package
+ properties:
+ name:
+ type: string
+ description: Human-readable SDK name
+ examples:
+ - "HubSpot UI Extensions"
+ - "Canva App UI Kit"
+ - "Salesforce Lightning Web Components"
+
+ packageManager:
+ type: string
+ description: Package manager ecosystem
+ enum:
+ - npm
+ - yarn
+ - pip
+ - maven
+ - gradle
+ - nuget
+ - cargo
+ - go
+ - composer
+ default: npm
+
+ package:
+ type: string
+ description: Package identifier (e.g., npm package name)
+ examples:
+ - "@hubspot/ui-extensions"
+ - "@canva/app-ui-kit"
+ - "lightning/ui"
+
+ version:
+ type: string
+ description: Recommended or minimum version
+ examples:
+ - "^0.11.2"
+ - ">=1.0.0"
+
+ repository:
+ type: string
+ format: uri
+ description: Source code repository URL
+
+ documentation:
+ type: string
+ format: uri
+ description: SDK documentation URL
+
+ # Installation & Setup
+ installCommand:
+ type: string
+ description: Full install command for quick setup
+ examples:
+ - "npm install @hubspot/ui-extensions"
+ - "npx create-canva-app my-app"
+ - "pip install stripe"
+
+ cdn:
+ type: string
+ format: uri
+ description: CDN URL for script tag loading (if supported)
+ examples:
+ - "https://js.stripe.com/v3/"
+ - "https://cdn.plaid.com/link/v2/stable/link-initialize.js"
+
+ cdnRequired:
+ type: boolean
+ description: Whether SDK must be loaded from CDN (cannot be bundled)
+ default: false
+
+ typesPackage:
+ type: string
+ description: TypeScript types package (if separate from main package)
+ examples:
+ - "@types/stripe"
+ - "@figma/plugin-typings"
+
+ # Developer Experience
+ starterTemplate:
+ type: object
+ description: Starter template/scaffolding for new projects
+ properties:
+ command:
+ type: string
+ description: CLI command to scaffold new project
+ examples:
+ - "npx create-canva-app"
+ - "hs project create"
+ - "sf force:lightning:component:create"
+ repository:
+ type: string
+ format: uri
+ description: GitHub template repository
+ documentation:
+ type: string
+ format: uri
+
+ cliTool:
+ type: object
+ description: Platform CLI tool for development
+ properties:
+ package:
+ type: string
+ description: CLI package name
+ examples:
+ - "@hubspot/cli"
+ - "@canva/cli"
+ - "sfdx-cli"
+ installCommand:
+ type: string
+ commands:
+ type: object
+ description: Key CLI commands
+ additionalProperties:
+ type: string
+ examples:
+ - dev: "hs project dev"
+ deploy: "hs project upload"
+ - dev: "canva app dev"
+ build: "canva app build"
+
+ exports:
+ type: object
+ description: Named exports from the SDK package
+ additionalProperties:
+ $ref: '#/components/schemas/SDKExport'
+
+ subpackages:
+ type: object
+ description: |
+ Additional subpackages within the SDK ecosystem.
+ Some SDKs split components across multiple packages.
+ additionalProperties:
+ type: object
+ properties:
+ package:
+ type: string
+ description:
+ type: string
+ exports:
+ type: object
+ additionalProperties:
+ $ref: '#/components/schemas/SDKExport'
+
+ SDKExport:
+ type: object
+ description: A named export from an SDK package
+ properties:
+ type:
+ type: string
+ enum:
+ - component
+ - hook
+ - utility
+ - icon
+ - token
+ - context
+ - type
+ description: Type of export
+
+ description:
+ type: string
+ description: What this export provides
+
+ deprecated:
+ type: boolean
+ default: false
+
+ since:
+ type: string
+ description: Version when this export was added
+
+ # =========================================================================
+ # COMPONENT CATALOG
+ # =========================================================================
+
+ ComponentCatalog:
+ type: object
+ description: |
+ The catalog of UI components available on this platform.
+ Components can be categorized and mapped to web standards.
+ properties:
+ categories:
+ type: object
+ description: Component categories (layout, input, display, etc.)
+ additionalProperties:
+ $ref: '#/components/schemas/ComponentCategory'
+
+ components:
+ type: object
+ description: All components indexed by canonical identifier
+ additionalProperties:
+ $ref: '#/components/schemas/Component'
+
+ ComponentCategory:
+ type: object
+ properties:
+ name:
+ type: string
+ description:
+ type: string
+ components:
+ type: array
+ items:
+ type: string
+ description: References to component identifiers in this category
+
+ Component:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ description: Component display name
+
+ description:
+ type: string
+ description: What this component does
+
+ category:
+ type: string
+ description: Category this component belongs to
+ examples:
+ - layout
+ - input
+ - display
+ - navigation
+ - overlay
+ - feedback
+ - data
+
+ sdkBinding:
+ $ref: '#/components/schemas/SDKBinding'
+
+ webStandardMapping:
+ $ref: '#/components/schemas/WebStandardMapping'
+
+ props:
+ type: object
+ description: Component properties/attributes (JSON Schema format)
+ additionalProperties: true
+
+ slots:
+ type: object
+ description: Named slots/children this component accepts
+ additionalProperties:
+ $ref: '#/components/schemas/Slot'
+
+ events:
+ type: object
+ description: Events this component can emit
+ additionalProperties:
+ $ref: '#/components/schemas/ComponentEvent'
+
+ variants:
+ type: array
+ description: Visual or behavioral variants
+ items:
+ type: string
+
+ accessibility:
+ $ref: '#/components/schemas/AccessibilityInfo'
+
+ examples:
+ type: array
+ items:
+ $ref: '#/components/schemas/ComponentExample'
+
+ SDKBinding:
+ type: object
+ description: How to import this component from an SDK
+ required:
+ - sdk
+ - export
+ properties:
+ sdk:
+ type: string
+ description: Reference to SDK identifier in the sdks object
+
+ subpackage:
+ type: string
+ description: Subpackage within the SDK (if applicable)
+
+ export:
+ type: string
+ description: Named export from the package
+
+ importPath:
+ type: string
+ description: |
+ Full import path if different from default package.
+ Example: "@hubspot/ui-extensions/crm"
+
+ WebStandardMapping:
+ type: object
+ description: |
+ Maps this platform component to web platform standards.
+ Enables cross-platform compatibility and semantic understanding.
+ properties:
+ htmlElement:
+ type: string
+ description: Closest HTML element equivalent
+ examples:
+ - button
+ - input
+ - select
+ - dialog
+ - form
+
+ ariaRole:
+ type: string
+ description: ARIA role this component fulfills
+ examples:
+ - button
+ - textbox
+ - listbox
+ - dialog
+ - alert
+
+ webComponent:
+ type: string
+ description: Web Components standard equivalent (if any)
+
+ semanticType:
+ type: string
+ description: Semantic UI pattern type
+ enum:
+ - action
+ - input
+ - display
+ - layout
+ - navigation
+ - feedback
+ - container
+
+ Slot:
+ type: object
+ properties:
+ description:
+ type: string
+ required:
+ type: boolean
+ default: false
+ accepts:
+ type: array
+ description: Component types this slot accepts
+ items:
+ type: string
+
+ ComponentEvent:
+ type: object
+ properties:
+ description:
+ type: string
+ payload:
+ type: object
+ description: JSON Schema for event payload
+
+ AccessibilityInfo:
+ type: object
+ properties:
+ keyboardSupport:
+ type: boolean
+ screenReaderSupport:
+ type: boolean
+ focusManagement:
+ type: string
+ notes:
+ type: string
+
+ ComponentExample:
+ type: object
+ properties:
+ title:
+ type: string
+ description:
+ type: string
+ code:
+ type: string
+ description: Example code snippet
+ language:
+ type: string
+ default: jsx
+
+ # =========================================================================
+ # RENDERING ENGINES
+ # =========================================================================
+
+ RenderingEngine:
+ type: object
+ description: |
+ A rendering engine that can interpret UI definitions and produce rendered output.
+ Supports multiple paradigms: declarative JSON, React components, web components, etc.
+ required:
+ - type
+ properties:
+ type:
+ type: string
+ enum:
+ - jsonForms
+ - jsonSchema
+ - mcpApps
+ - react
+ - webComponents
+ - lwc
+ - custom
+ description: Rendering paradigm
+
+ name:
+ type: string
+ description: Human-readable engine name
+
+ description:
+ type: string
+
+ schemaSupport:
+ type: object
+ description: Schema-based rendering configuration
+ properties:
+ dataSchema:
+ type: string
+ enum:
+ - jsonSchema
+ - custom
+ description: Schema format for data definition
+
+ uiSchema:
+ type: string
+ enum:
+ - jsonFormsUISchema
+ - mcpAppsTemplate
+ - custom
+ description: Schema format for UI definition
+
+ customRenderers:
+ type: boolean
+ description: Whether custom renderers can be registered
+ default: false
+
+ sandboxing:
+ $ref: '#/components/schemas/SandboxConfig'
+
+ SandboxConfig:
+ type: object
+ description: Security sandboxing configuration for rendered UI
+ properties:
+ iframeSandbox:
+ type: boolean
+ description: Whether UI runs in sandboxed iframe
+
+ sandboxAttributes:
+ type: array
+ items:
+ type: string
+ description: iframe sandbox attribute values
+ examples:
+ - allow-scripts
+ - allow-forms
+ - allow-same-origin
+
+ cspPolicy:
+ type: string
+ description: Content Security Policy for rendered content
+
+ # =========================================================================
+ # POLICIES
+ # =========================================================================
+
+ Policies:
+ type: object
+ description: |
+ Platform policies governing UI component usage, custom components,
+ and publishing requirements.
+ properties:
+
+ componentRequirement:
+ $ref: '#/components/schemas/ComponentRequirementPolicy'
+
+ customComponents:
+ $ref: '#/components/schemas/CustomComponentPolicy'
+
+ publishing:
+ $ref: '#/components/schemas/PublishingPolicy'
+
+ designGuidelines:
+ $ref: '#/components/schemas/DesignGuidelinesPolicy'
+
+ ComponentRequirementPolicy:
+ type: object
+ description: |
+ Whether platform-provided components are required.
+
+ Examples:
+ - HubSpot: Required (can only use SDK components)
+ - Canva: Strongly recommended for public apps
+ - Miro: Optional (Mirotone is available but not required)
+ properties:
+ level:
+ type: string
+ enum:
+ - required
+ - recommended
+ - optional
+ description: |
+ - required: Must use platform components exclusively
+ - recommended: Platform components preferred, alternatives allowed
+ - optional: Platform components available but not required
+
+ scope:
+ type: string
+ enum:
+ - all
+ - publicApps
+ - marketplaceApps
+ description: What app types this requirement applies to
+
+ rationale:
+ type: string
+ description: Why this policy exists
+
+ exceptions:
+ type: array
+ items:
+ type: string
+ description: Documented exceptions to this policy
+
+ CustomComponentPolicy:
+ type: object
+ description: |
+ Whether developers can bring their own (BYO) components.
+
+ Key dimensions:
+ - Allowed at all?
+ - Must wrap platform primitives?
+ - Must follow design system?
+ - Review required for marketplace?
+ properties:
+ allowed:
+ type: boolean
+ description: Whether custom components are permitted at all
+
+ constraints:
+ type: array
+ items:
+ type: string
+ enum:
+ - mustWrapPlatformPrimitives
+ - mustFollowDesignSystem
+ - mustPassAccessibilityAudit
+ - requiresReview
+ - sandboxOnly
+ description: Constraints on custom components
+
+ registrationRequired:
+ type: boolean
+ description: Whether custom components must be registered
+ default: false
+
+ approvalRequired:
+ type: boolean
+ description: Whether custom components require platform approval
+ default: false
+
+ documentation:
+ type: string
+ format: uri
+ description: Documentation for custom component requirements
+
+ PublishingPolicy:
+ type: object
+ description: |
+ Different rules for public/marketplace apps vs private/internal apps.
+
+ Common pattern:
+ - Private apps: More flexibility, fewer requirements
+ - Public apps: Strict component requirements, review process
+ properties:
+
+ privateApps:
+ type: object
+ properties:
+ componentRequirement:
+ type: string
+ enum: [required, recommended, optional]
+ customComponentsAllowed:
+ type: boolean
+ reviewRequired:
+ type: boolean
+ notes:
+ type: string
+
+ publicApps:
+ type: object
+ properties:
+ componentRequirement:
+ type: string
+ enum: [required, recommended, optional]
+ customComponentsAllowed:
+ type: boolean
+ reviewRequired:
+ type: boolean
+ designReviewRequired:
+ type: boolean
+ accessibilityAuditRequired:
+ type: boolean
+ notes:
+ type: string
+
+ marketplaceApps:
+ type: object
+ description: Apps published to official marketplace (may differ from public)
+ properties:
+ componentRequirement:
+ type: string
+ enum: [required, recommended, optional]
+ customComponentsAllowed:
+ type: boolean
+ certificationRequired:
+ type: boolean
+ notes:
+ type: string
+
+ DesignGuidelinesPolicy:
+ type: object
+ description: Platform design system and guidelines
+ properties:
+ required:
+ type: boolean
+ description: Whether following guidelines is mandatory
+
+ designSystem:
+ type: string
+ description: Name of the design system
+ examples:
+ - "Lightning Design System"
+ - "Canva Design Guidelines"
+ - "HubSpot Canvas"
+
+ designSystemUrl:
+ type: string
+ format: uri
+
+ designTokensProvided:
+ type: boolean
+ description: Whether design tokens are available for custom styling
+
+ # =========================================================================
+ # EXTENSION POINTS
+ # =========================================================================
+
+ ExtensionPoint:
+ type: object
+ description: |
+ A location in the host platform where UI can be injected.
+
+ Examples:
+ - Sidebar panel
+ - Modal dialog
+ - Card on a record page
+ - Toolbar button
+ - Canvas element (Miro, Canva)
+ required:
+ - id
+ - name
+ - type
+ - extensionType
+ properties:
+ id:
+ type: string
+ description: Unique identifier for this extension point
+
+ name:
+ type: string
+ description: Human-readable name
+
+ type:
+ type: string
+ enum:
+ - sidebar
+ - modal
+ - panel
+ - card
+ - toolbar
+ - contextMenu
+ - canvas
+ - composer
+ - fullPage
+ - embedded
+ description: Type of extension point
+
+ extensionType:
+ type: string
+ enum:
+ - jsonResponse
+ - codedComponents
+ - iframe
+ - embeddedSdk
+ - agentUI
+ description: |
+ How the developer provides UI for this extension point:
+ - jsonResponse: Developer returns JSON from endpoint, platform renders
+ - codedComponents: Developer writes code using platform SDK/UI Kit
+ - iframe: Developer provides full web app at URL
+ - embeddedSdk: Platform SDK embedded in developer's app
+ - agentUI: AI agent-driven UI with predeclared templates + custom iframe
+
+ extensionTypeConfig:
+ oneOf:
+ - $ref: '#/components/schemas/JsonResponseConfig'
+ - $ref: '#/components/schemas/CodedComponentsConfig'
+ - $ref: '#/components/schemas/IframeConfig'
+ - $ref: '#/components/schemas/EmbeddedSdkConfig'
+ - $ref: '#/components/schemas/AgentUIConfig'
+ description: Configuration specific to the extension type
+
+ description:
+ type: string
+
+ supportedComponents:
+ type: array
+ items:
+ type: string
+ description: Component types allowed at this extension point
+
+ constraints:
+ type: object
+ properties:
+ maxWidth:
+ type: integer
+ description: Maximum width in pixels
+ maxHeight:
+ type: integer
+ description: Maximum height in pixels
+ responsive:
+ type: boolean
+ description: Whether extension must be responsive
+
+ context:
+ type: object
+ description: Data context available at this extension point
+ properties:
+ provides:
+ type: array
+ items:
+ type: string
+ description: Context data types provided
+ examples:
+ - currentRecord
+ - selectedItems
+ - user
+ - conversation
+
+ actions:
+ type: array
+ items:
+ type: string
+ description: Actions that can be performed from this context
+
+ # =========================================================================
+ # MCP APPS INTEGRATION
+ # =========================================================================
+
+ MCPAppsIntegration:
+ type: object
+ description: |
+ Integration with MCP Apps specification for AI-driven UI.
+ Maps Fenestra components to MCP Apps UI resources.
+ properties:
+ supported:
+ type: boolean
+ description: Whether this platform supports MCP Apps
+
+ templateMappings:
+ type: object
+ description: Maps MCP App templates to Fenestra components
+ additionalProperties:
+ type: string
+
+ customTemplatesAllowed:
+ type: boolean
+ description: Whether custom MCP App templates are allowed
+
+ communicationProtocol:
+ type: string
+ enum:
+ - jsonRpc
+ - postMessage
+ - custom
+ description: Protocol for host-UI communication
+
+ # =========================================================================
+ # JSON FORMS INTEGRATION
+ # =========================================================================
+
+ JSONFormsIntegration:
+ type: object
+ description: |
+ Integration with JSON Forms specification for schema-driven UI.
+ Enables declarative form rendering from JSON Schema.
+ properties:
+ supported:
+ type: boolean
+ description: Whether this platform supports JSON Forms rendering
+
+ rendererSet:
+ type: string
+ enum:
+ - default
+ - material
+ - vanilla
+ - platform
+ - custom
+ description: Which JSON Forms renderer set to use
+
+ customRenderersAllowed:
+ type: boolean
+ description: Whether custom JSON Forms renderers can be registered
+
+ componentBindings:
+ type: object
+ description: Maps JSON Forms control types to platform components
+ additionalProperties:
+ type: string
+ examples:
+ text: TextField
+ number: NumberInput
+ boolean: Checkbox
+ date: DatePicker
+
+ # =========================================================================
+ # EXTENSION TYPE CONFIGURATIONS
+ # =========================================================================
+
+ JsonResponseConfig:
+ type: object
+ description: |
+ Configuration for JSON Response extension type.
+ Developer returns JSON from endpoint, platform renders pre-built components.
+
+ Examples: Slack Block Kit, Google Workspace Add-ons, Asana App Components
+ properties:
+ schema:
+ type: object
+ description: JSON Schema definition for valid responses
+ properties:
+ format:
+ type: string
+ description: Schema format identifier
+ examples:
+ - "google.apps.card.v1"
+ - "slack.blocks"
+ - "adaptive-cards"
+ - "custom"
+
+ version:
+ type: string
+ description: Schema version
+
+ schemaUrl:
+ type: string
+ format: uri
+ description: URL to full JSON Schema definition
+
+ encoding:
+ type: string
+ default: "UTF-8"
+
+ endpoint:
+ type: object
+ description: How the platform calls the developer's endpoint
+ properties:
+ method:
+ type: string
+ enum: [GET, POST]
+ default: POST
+
+ contentType:
+ type: string
+ default: "application/json"
+
+ timeout:
+ type: integer
+ description: Request timeout in seconds
+ default: 10
+
+ authentication:
+ type: string
+ enum:
+ - none
+ - oauth
+ - jwt
+ - signedRequest
+ - apiKey
+ description: How requests are authenticated
+
+ contextProvided:
+ type: array
+ items:
+ type: string
+ description: Context data sent with each request
+ examples:
+ - user
+ - record
+ - locale
+ - permissions
+
+ interactivity:
+ type: object
+ description: How user interactions are handled
+ properties:
+ callbackUrl:
+ type: boolean
+ description: Whether platform POSTs interactions to callback URL
+
+ payloadTypes:
+ type: array
+ items:
+ type: string
+ description: Types of interaction payloads
+ examples:
+ - block_actions
+ - view_submission
+ - form_submit
+
+ CodedComponentsConfig:
+ type: object
+ description: |
+ Configuration for Coded Components extension type.
+ Developer writes code using platform's SDK/UI Kit.
+
+ Examples: HubSpot UI Extensions, Salesforce LWC, Canva Apps SDK
+ properties:
+ sdk:
+ type: string
+ description: Reference to SDK in the sdks object
+
+ framework:
+ type: string
+ enum:
+ - react
+ - vue
+ - lwc
+ - webComponents
+ - agnostic
+ description: Required or primary framework
+
+ runtime:
+ type: object
+ description: How developer code is executed
+ properties:
+ type:
+ type: string
+ enum:
+ - sandboxedIframe
+ - webWorker
+ - directExecution
+ description: Execution environment
+
+ bundling:
+ type: string
+ enum:
+ - platformBuild
+ - developerBuild
+ - cdn
+ description: How code is bundled and deployed
+
+ hostInteraction:
+ $ref: '#/components/schemas/JsSdkConfig'
+
+ IframeConfig:
+ type: object
+ description: |
+ Configuration for Iframe extension type.
+ Developer provides full web app at URL, platform loads in iframe.
+
+ Examples: Front Plugins, Zendesk Apps, Figma Plugins
+ properties:
+ sandboxAttributes:
+ type: array
+ items:
+ type: string
+ description: iframe sandbox attribute values
+ examples:
+ - allow-scripts
+ - allow-forms
+ - allow-same-origin
+ - allow-popups
+
+ cspRequirements:
+ type: string
+ description: Required Content Security Policy
+
+ sizeConstraints:
+ type: object
+ properties:
+ minWidth:
+ type: integer
+ maxWidth:
+ type: integer
+ minHeight:
+ type: integer
+ maxHeight:
+ type: integer
+ resizable:
+ type: boolean
+ description: Whether iframe can be resized dynamically
+
+ communication:
+ $ref: '#/components/schemas/JsSdkConfig'
+
+ EmbeddedSdkConfig:
+ type: object
+ description: |
+ Configuration for Embedded SDK extension type.
+ Platform SDK is embedded in developer's own application.
+
+ Examples: Stripe Elements, Plaid Link, PayPal Buttons
+ properties:
+ sdk:
+ type: object
+ description: SDK package details
+ properties:
+ package:
+ type: string
+ description: npm/CDN package name
+
+ cdn:
+ type: string
+ format: uri
+ description: CDN URL (often required for security)
+
+ cdnRequired:
+ type: boolean
+ description: Whether SDK must be loaded from CDN (cannot bundle)
+ default: false
+
+ mountPattern:
+ type: string
+ enum:
+ - domSelector
+ - reactComponent
+ - webComponent
+ - function
+ description: How SDK components are mounted
+
+ theming:
+ type: object
+ description: Styling/theming capabilities
+ properties:
+ system:
+ type: string
+ description: Theming system name
+ examples:
+ - "Appearance API"
+ - "Theme options"
+ - "CSS variables"
+
+ prebuiltThemes:
+ type: array
+ items:
+ type: string
+ description: Available pre-built themes
+
+ customizable:
+ type: boolean
+ description: Whether theming is customizable
+
+ variables:
+ type: array
+ items:
+ type: string
+ description: Customizable theme variables
+
+ communication:
+ type: object
+ properties:
+ pattern:
+ type: string
+ enum:
+ - callbacks
+ - events
+ - promises
+ - observables
+ description: Primary async communication pattern
+
+ events:
+ type: array
+ items:
+ type: string
+ description: Events the SDK can emit
+
+ AgentUIConfig:
+ type: object
+ description: |
+ Configuration for Agent UI extension type.
+ AI agents drive UI through predeclared templates + custom iframe fallback.
+
+ Based on the MCP Apps proposal - enables AI-driven UI through structured
+ templates while preserving escape hatch to full custom UI.
+
+ Examples: MCP Apps hosts, AI assistant sidebars, LLM-powered interfaces
+ properties:
+ templates:
+ type: object
+ description: Pre-declared UI templates the agent can invoke
+ properties:
+ supported:
+ type: array
+ items:
+ type: string
+ description: Template types supported by the host
+ examples:
+ - form
+ - confirmation
+ - progress
+ - result
+ - error
+ - list
+ - detail
+ - media
+
+ definitions:
+ type: object
+ description: Template definitions with their schemas
+ additionalProperties:
+ $ref: '#/components/schemas/AgentUITemplate'
+
+ customUI:
+ type: object
+ description: Custom iframe fallback for complex UI needs
+ properties:
+ allowed:
+ type: boolean
+ description: Whether custom iframe UI is supported
+ default: true
+
+ sandboxAttributes:
+ type: array
+ items:
+ type: string
+ description: iframe sandbox attributes for custom UI
+
+ sizeConstraints:
+ type: object
+ properties:
+ maxWidth:
+ type: integer
+ maxHeight:
+ type: integer
+ resizable:
+ type: boolean
+
+ communication:
+ type: object
+ description: How agent and UI communicate
+ properties:
+ protocol:
+ type: string
+ enum:
+ - jsonRpc
+ - postMessage
+ - mcp
+ description: Primary communication protocol
+ default: jsonRpc
+
+ channels:
+ type: array
+ items:
+ type: string
+ description: Communication channels available
+ examples:
+ - templates
+ - customUI
+ - events
+ - actions
+
+ agentCapabilities:
+ type: object
+ description: What the agent can do through the UI
+ properties:
+ invokeTemplates:
+ type: boolean
+ description: Can invoke pre-declared templates
+ default: true
+
+ openCustomUI:
+ type: boolean
+ description: Can open custom iframe UI
+ default: true
+
+ receiveEvents:
+ type: boolean
+ description: Can receive UI events (clicks, submissions)
+ default: true
+
+ closeUI:
+ type: boolean
+ description: Can programmatically close UI
+ default: true
+
+ chainInteractions:
+ type: boolean
+ description: Can chain multiple UI interactions
+ default: true
+
+ AgentUITemplate:
+ type: object
+ description: Definition of a pre-declared agent UI template
+ properties:
+ name:
+ type: string
+ description: Template identifier
+
+ description:
+ type: string
+ description: What this template is used for
+
+ inputSchema:
+ type: object
+ description: JSON Schema for template input data
+
+ outputSchema:
+ type: object
+ description: JSON Schema for template output (user response)
+
+ rendering:
+ type: object
+ description: How the template is rendered
+ properties:
+ type:
+ type: string
+ enum:
+ - platform
+ - jsonForms
+ - custom
+ description: Rendering strategy
+
+ component:
+ type: string
+ description: Platform component used for rendering
+
+ interactivity:
+ type: object
+ properties:
+ submitButton:
+ type: boolean
+ description: Has a submit action
+
+ cancelButton:
+ type: boolean
+ description: Has a cancel action
+
+ events:
+ type: array
+ items:
+ type: string
+ description: Events this template can emit
+
+ # =========================================================================
+ # JAVASCRIPT SDK CONFIGURATION
+ # =========================================================================
+
+ JsSdkConfig:
+ type: object
+ description: |
+ Configuration for JavaScript SDK that enables host interaction.
+ Cross-cutting concern that applies to multiple extension types.
+ properties:
+ globalObject:
+ type: string
+ description: Global window object name
+ examples:
+ - miro
+ - Front
+ - ZAFClient
+ - figma
+ - Stripe
+
+ package:
+ type: string
+ description: npm package name (if applicable)
+
+ cdn:
+ type: string
+ format: uri
+ description: CDN script URL
+
+ initialization:
+ type: object
+ properties:
+ method:
+ type: string
+ description: How SDK is initialized
+ examples:
+ - "auto"
+ - "ZAFClient.init()"
+ - "loadStripe(key)"
+
+ async:
+ type: boolean
+ description: Whether initialization is async
+
+ namespaces:
+ type: object
+ description: SDK namespace structure
+ additionalProperties:
+ type: object
+ properties:
+ description:
+ type: string
+ methods:
+ type: array
+ items:
+ type: string
+
+ capabilities:
+ type: object
+ description: What the SDK can do
+ properties:
+ context:
+ type: boolean
+ description: Can access current context/state
+
+ uiActions:
+ type: boolean
+ description: Can trigger platform UI (toasts, modals)
+
+ dataActions:
+ type: boolean
+ description: Can perform CRUD on platform data
+
+ events:
+ type: boolean
+ description: Can subscribe to platform events
+
+ asyncPattern:
+ type: string
+ enum:
+ - promises
+ - callbacks
+ - observables
+ - sync
+ description: Primary async pattern used
diff --git a/specs/fenestra/schemas/core/v0.1/fenestra-core.schema.json b/specs/fenestra/schemas/core/v0.1/fenestra-core.schema.json
new file mode 100644
index 0000000..53b433a
--- /dev/null
+++ b/specs/fenestra/schemas/core/v0.1/fenestra-core.schema.json
@@ -0,0 +1,1317 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://spec.openapis.org/fenestra/core/v0.1/schema.json",
+ "title": "Fenestra Core Specification Schema",
+ "description": "JSON Schema for validating Fenestra Core Description documents",
+ "type": "object",
+ "required": [
+ "fenestra",
+ "info"
+ ],
+ "properties": {
+ "fenestra": {
+ "type": "string",
+ "description": "Fenestra specification version",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+(-[a-zA-Z0-9]+)?$"
+ },
+ "info": {
+ "$ref": "#/$defs/Info"
+ },
+ "platform": {
+ "$ref": "#/$defs/Platform"
+ },
+ "sdks": {
+ "type": "object",
+ "description": "SDK ecosystem definitions indexed by SDK identifier",
+ "additionalProperties": {
+ "$ref": "#/$defs/SDK"
+ }
+ },
+ "componentCatalog": {
+ "$ref": "#/$defs/ComponentCatalog"
+ },
+ "renderingEngines": {
+ "type": "object",
+ "description": "Supported rendering engine configurations",
+ "additionalProperties": {
+ "$ref": "#/$defs/RenderingEngine"
+ }
+ },
+ "policies": {
+ "$ref": "#/$defs/Policies"
+ },
+ "extensionPoints": {
+ "type": "array",
+ "description": "Where UI can be injected in the host platform",
+ "items": {
+ "$ref": "#/$defs/ExtensionPoint"
+ }
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "description": "Specification extension"
+ }
+ },
+ "$defs": {
+ "Info": {
+ "type": "object",
+ "required": [
+ "title",
+ "version"
+ ],
+ "properties": {
+ "title": {
+ "type": "string",
+ "description": "Human-readable title for the Fenestra Description"
+ },
+ "summary": {
+ "type": "string",
+ "description": "A short summary of the platform's UI capabilities"
+ },
+ "description": {
+ "type": "string",
+ "description": "Extended description (CommonMark supported)"
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of this Fenestra Description document"
+ },
+ "termsOfService": {
+ "type": "string",
+ "format": "uri"
+ },
+ "contact": {
+ "$ref": "#/$defs/Contact"
+ },
+ "license": {
+ "$ref": "#/$defs/License"
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "Contact": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ },
+ "email": {
+ "type": "string",
+ "format": "email"
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "License": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "identifier": {
+ "type": "string",
+ "description": "SPDX license expression"
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "Platform": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Platform name"
+ },
+ "vendor": {
+ "type": "string",
+ "description": "Platform vendor/company name"
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri",
+ "description": "URL to platform developer documentation"
+ },
+ "appMarketplace": {
+ "type": "string",
+ "format": "uri",
+ "description": "URL to the platform's app marketplace"
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "SDK": {
+ "type": "object",
+ "required": [
+ "name",
+ "packageManager",
+ "package"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Human-readable SDK name"
+ },
+ "packageManager": {
+ "type": "string",
+ "enum": [
+ "npm",
+ "yarn",
+ "pip",
+ "maven",
+ "gradle",
+ "nuget",
+ "cargo",
+ "go",
+ "composer",
+ "cocoapods",
+ "carthage",
+ "swift-package-manager"
+ ]
+ },
+ "package": {
+ "type": "string",
+ "description": "Package identifier"
+ },
+ "version": {
+ "type": "string",
+ "description": "Recommended or minimum version"
+ },
+ "platform": {
+ "type": "string",
+ "enum": [
+ "web",
+ "ios",
+ "android",
+ "react-native",
+ "flutter",
+ "electron"
+ ],
+ "default": "web",
+ "description": "Target platform"
+ },
+ "mobile": {
+ "$ref": "#/$defs/MobileSDK"
+ },
+ "repository": {
+ "type": "string",
+ "format": "uri"
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri"
+ },
+ "installCommand": {
+ "type": "string",
+ "description": "Full install command for quick setup"
+ },
+ "cdn": {
+ "type": "string",
+ "format": "uri",
+ "description": "CDN URL for script tag loading"
+ },
+ "cdnRequired": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether SDK must be loaded from CDN"
+ },
+ "typesPackage": {
+ "type": "string",
+ "description": "TypeScript types package if separate"
+ },
+ "starterTemplate": {
+ "$ref": "#/$defs/StarterTemplate"
+ },
+ "cliTool": {
+ "$ref": "#/$defs/CliTool"
+ },
+ "exports": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/SDKExport"
+ }
+ },
+ "subpackages": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/Subpackage"
+ }
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "StarterTemplate": {
+ "type": "object",
+ "properties": {
+ "command": {
+ "type": "string"
+ },
+ "repository": {
+ "type": "string",
+ "format": "uri"
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri"
+ }
+ }
+ },
+ "CliTool": {
+ "type": "object",
+ "properties": {
+ "package": {
+ "type": "string"
+ },
+ "installCommand": {
+ "type": "string"
+ },
+ "commands": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "SDKExport": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "component",
+ "hook",
+ "utility",
+ "icon",
+ "token",
+ "context",
+ "type"
+ ]
+ },
+ "description": {
+ "type": "string"
+ },
+ "deprecated": {
+ "type": "boolean",
+ "default": false
+ },
+ "since": {
+ "type": "string"
+ }
+ }
+ },
+ "Subpackage": {
+ "type": "object",
+ "properties": {
+ "package": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "exports": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/SDKExport"
+ }
+ }
+ }
+ },
+ "MobileSDK": {
+ "type": "object",
+ "description": "Mobile-specific SDK requirements",
+ "properties": {
+ "minOsVersion": {
+ "type": "string"
+ },
+ "targetOsVersion": {
+ "type": "string"
+ },
+ "capabilities": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "permissions": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "architectures": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "frameworks": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "appStoreGuidelines": {
+ "type": "string",
+ "format": "uri"
+ }
+ }
+ },
+ "ComponentCatalog": {
+ "type": "object",
+ "properties": {
+ "categories": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/ComponentCategory"
+ }
+ },
+ "components": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/Component"
+ }
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "ComponentCategory": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "components": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "Component": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "category": {
+ "type": "string"
+ },
+ "sdkBinding": {
+ "$ref": "#/$defs/SDKBinding"
+ },
+ "webStandardMapping": {
+ "$ref": "#/$defs/WebStandardMapping"
+ },
+ "props": {
+ "type": "object",
+ "description": "Component properties (JSON Schema format)"
+ },
+ "slots": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/Slot"
+ }
+ },
+ "events": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/ComponentEvent"
+ }
+ },
+ "variants": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "accessibility": {
+ "$ref": "#/$defs/Accessibility"
+ },
+ "examples": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/ComponentExample"
+ }
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "SDKBinding": {
+ "type": "object",
+ "required": [
+ "sdk",
+ "export"
+ ],
+ "properties": {
+ "sdk": {
+ "type": "string"
+ },
+ "subpackage": {
+ "type": "string"
+ },
+ "export": {
+ "type": "string"
+ },
+ "importPath": {
+ "type": "string"
+ }
+ }
+ },
+ "WebStandardMapping": {
+ "type": "object",
+ "properties": {
+ "htmlElement": {
+ "type": "string"
+ },
+ "ariaRole": {
+ "type": "string"
+ },
+ "webComponent": {
+ "type": "string"
+ },
+ "semanticType": {
+ "type": "string",
+ "enum": [
+ "action",
+ "input",
+ "display",
+ "layout",
+ "navigation",
+ "feedback",
+ "container"
+ ]
+ }
+ }
+ },
+ "Slot": {
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string"
+ },
+ "required": {
+ "type": "boolean",
+ "default": false
+ },
+ "accepts": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "ComponentEvent": {
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string"
+ },
+ "payload": {
+ "type": "object"
+ }
+ }
+ },
+ "Accessibility": {
+ "type": "object",
+ "properties": {
+ "keyboardSupport": {
+ "type": "boolean"
+ },
+ "screenReaderSupport": {
+ "type": "boolean"
+ },
+ "focusManagement": {
+ "type": "string"
+ },
+ "notes": {
+ "type": "string"
+ }
+ }
+ },
+ "ComponentExample": {
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "code": {
+ "type": "string"
+ },
+ "language": {
+ "type": "string",
+ "default": "jsx"
+ }
+ }
+ },
+ "RenderingEngine": {
+ "type": "object",
+ "required": [
+ "type"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "jsonForms",
+ "jsonSchema",
+ "mcpApps",
+ "react",
+ "webComponents",
+ "lwc",
+ "custom"
+ ]
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "schemaSupport": {
+ "$ref": "#/$defs/SchemaSupport"
+ },
+ "sandboxing": {
+ "$ref": "#/$defs/SandboxConfig"
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "SchemaSupport": {
+ "type": "object",
+ "properties": {
+ "dataSchema": {
+ "type": "string",
+ "enum": [
+ "jsonSchema",
+ "custom"
+ ]
+ },
+ "uiSchema": {
+ "type": "string",
+ "enum": [
+ "jsonFormsUISchema",
+ "mcpAppsTemplate",
+ "custom"
+ ]
+ },
+ "customRenderers": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "SandboxConfig": {
+ "type": "object",
+ "properties": {
+ "iframeSandbox": {
+ "type": "boolean"
+ },
+ "sandboxAttributes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "cspPolicy": {
+ "type": "string"
+ }
+ }
+ },
+ "Policies": {
+ "type": "object",
+ "properties": {
+ "componentRequirement": {
+ "$ref": "#/$defs/ComponentRequirementPolicy"
+ },
+ "customComponents": {
+ "$ref": "#/$defs/CustomComponentPolicy"
+ },
+ "publishing": {
+ "$ref": "#/$defs/PublishingPolicy"
+ },
+ "designGuidelines": {
+ "$ref": "#/$defs/DesignGuidelinesPolicy"
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "ComponentRequirementPolicy": {
+ "type": "object",
+ "properties": {
+ "level": {
+ "type": "string",
+ "enum": [
+ "required",
+ "recommended",
+ "optional"
+ ]
+ },
+ "scope": {
+ "type": "string",
+ "enum": [
+ "all",
+ "publicApps",
+ "marketplaceApps"
+ ]
+ },
+ "rationale": {
+ "type": "string"
+ },
+ "exceptions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "CustomComponentPolicy": {
+ "type": "object",
+ "properties": {
+ "allowed": {
+ "type": "boolean"
+ },
+ "constraints": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "mustWrapPlatformPrimitives",
+ "mustFollowDesignSystem",
+ "mustPassAccessibilityAudit",
+ "requiresReview",
+ "sandboxOnly"
+ ]
+ }
+ },
+ "registrationRequired": {
+ "type": "boolean",
+ "default": false
+ },
+ "approvalRequired": {
+ "type": "boolean",
+ "default": false
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri"
+ }
+ }
+ },
+ "PublishingPolicy": {
+ "type": "object",
+ "properties": {
+ "privateApps": {
+ "$ref": "#/$defs/AppPolicy"
+ },
+ "publicApps": {
+ "$ref": "#/$defs/AppPolicy"
+ },
+ "marketplaceApps": {
+ "$ref": "#/$defs/AppPolicy"
+ }
+ }
+ },
+ "AppPolicy": {
+ "type": "object",
+ "properties": {
+ "componentRequirement": {
+ "type": "string",
+ "enum": [
+ "required",
+ "recommended",
+ "optional"
+ ]
+ },
+ "customComponentsAllowed": {
+ "type": "boolean"
+ },
+ "reviewRequired": {
+ "type": "boolean"
+ },
+ "designReviewRequired": {
+ "type": "boolean"
+ },
+ "accessibilityAuditRequired": {
+ "type": "boolean"
+ },
+ "certificationRequired": {
+ "type": "boolean"
+ },
+ "notes": {
+ "type": "string"
+ }
+ }
+ },
+ "DesignGuidelinesPolicy": {
+ "type": "object",
+ "properties": {
+ "required": {
+ "type": "boolean"
+ },
+ "designSystem": {
+ "type": "string"
+ },
+ "designSystemUrl": {
+ "type": "string",
+ "format": "uri"
+ },
+ "designTokensProvided": {
+ "type": "boolean"
+ }
+ }
+ },
+ "ExtensionPoint": {
+ "type": "object",
+ "required": [
+ "id",
+ "name",
+ "type",
+ "extensionType"
+ ],
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "sidebar",
+ "modal",
+ "panel",
+ "card",
+ "toolbar",
+ "contextMenu",
+ "canvas",
+ "composer",
+ "fullPage",
+ "embedded"
+ ]
+ },
+ "extensionType": {
+ "type": "string",
+ "enum": [
+ "jsonResponse",
+ "codedComponents",
+ "iframe",
+ "embeddedSdk"
+ ]
+ },
+ "extensionTypeConfig": {
+ "type": "object",
+ "description": "Configuration specific to the extension type. Schema varies based on extensionType value."
+ },
+ "description": {
+ "type": "string"
+ },
+ "supportedComponents": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "constraints": {
+ "$ref": "#/$defs/Constraints"
+ },
+ "context": {
+ "$ref": "#/$defs/Context"
+ }
+ },
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "extensionType": {
+ "const": "jsonResponse"
+ }
+ },
+ "required": [
+ "extensionType"
+ ]
+ },
+ "then": {
+ "properties": {
+ "extensionTypeConfig": {
+ "$ref": "#/$defs/JsonResponseConfig"
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "extensionType": {
+ "const": "codedComponents"
+ }
+ },
+ "required": [
+ "extensionType"
+ ]
+ },
+ "then": {
+ "properties": {
+ "extensionTypeConfig": {
+ "$ref": "#/$defs/CodedComponentsConfig"
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "extensionType": {
+ "const": "iframe"
+ }
+ },
+ "required": [
+ "extensionType"
+ ]
+ },
+ "then": {
+ "properties": {
+ "extensionTypeConfig": {
+ "$ref": "#/$defs/IframeConfig"
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "extensionType": {
+ "const": "embeddedSdk"
+ }
+ },
+ "required": [
+ "extensionType"
+ ]
+ },
+ "then": {
+ "properties": {
+ "extensionTypeConfig": {
+ "$ref": "#/$defs/EmbeddedSdkConfig"
+ }
+ }
+ }
+ }
+ ],
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "Constraints": {
+ "type": "object",
+ "properties": {
+ "maxWidth": {
+ "type": "integer"
+ },
+ "maxHeight": {
+ "type": "integer"
+ },
+ "responsive": {
+ "type": "boolean"
+ }
+ }
+ },
+ "Context": {
+ "type": "object",
+ "properties": {
+ "provides": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "actions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "JsonResponseConfig": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "schema": {
+ "$ref": "#/$defs/ResponseSchema"
+ },
+ "endpoint": {
+ "$ref": "#/$defs/Endpoint"
+ },
+ "interactivity": {
+ "$ref": "#/$defs/Interactivity"
+ }
+ }
+ },
+ "ResponseSchema": {
+ "type": "object",
+ "properties": {
+ "format": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "schemaUrl": {
+ "type": "string",
+ "format": "uri"
+ },
+ "encoding": {
+ "type": "string",
+ "default": "UTF-8"
+ }
+ }
+ },
+ "Endpoint": {
+ "type": "object",
+ "properties": {
+ "method": {
+ "type": "string",
+ "enum": [
+ "GET",
+ "POST"
+ ],
+ "default": "POST"
+ },
+ "contentType": {
+ "type": "string",
+ "default": "application/json"
+ },
+ "timeout": {
+ "type": "integer",
+ "default": 10
+ },
+ "authentication": {
+ "type": "string",
+ "enum": [
+ "none",
+ "oauth",
+ "jwt",
+ "signedRequest",
+ "apiKey"
+ ]
+ },
+ "contextProvided": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "Interactivity": {
+ "type": "object",
+ "properties": {
+ "callbackUrl": {
+ "type": "boolean"
+ },
+ "payloadTypes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "CodedComponentsConfig": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sdk": {
+ "type": "string"
+ },
+ "framework": {
+ "type": "string",
+ "enum": [
+ "react",
+ "vue",
+ "lwc",
+ "webComponents",
+ "agnostic"
+ ]
+ },
+ "runtime": {
+ "$ref": "#/$defs/Runtime"
+ },
+ "hostInteraction": {
+ "$ref": "#/$defs/JsSdkConfig"
+ }
+ }
+ },
+ "Runtime": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "sandboxedIframe",
+ "webWorker",
+ "directExecution"
+ ]
+ },
+ "bundling": {
+ "type": "string",
+ "enum": [
+ "platformBuild",
+ "developerBuild",
+ "cdn"
+ ]
+ }
+ }
+ },
+ "IframeConfig": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sandboxAttributes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "cspRequirements": {
+ "type": "string"
+ },
+ "sizeConstraints": {
+ "$ref": "#/$defs/SizeConstraints"
+ },
+ "communication": {
+ "$ref": "#/$defs/JsSdkConfig"
+ }
+ }
+ },
+ "SizeConstraints": {
+ "type": "object",
+ "properties": {
+ "minWidth": {
+ "type": "integer"
+ },
+ "maxWidth": {
+ "type": "integer"
+ },
+ "minHeight": {
+ "type": "integer"
+ },
+ "maxHeight": {
+ "type": "integer"
+ },
+ "resizable": {
+ "type": "boolean"
+ }
+ }
+ },
+ "EmbeddedSdkConfig": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sdk": {
+ "$ref": "#/$defs/EmbeddedSdkDetails"
+ },
+ "mountPattern": {
+ "type": "string",
+ "enum": [
+ "domSelector",
+ "reactComponent",
+ "webComponent",
+ "function"
+ ]
+ },
+ "theming": {
+ "$ref": "#/$defs/Theming"
+ },
+ "communication": {
+ "$ref": "#/$defs/Communication"
+ }
+ }
+ },
+ "EmbeddedSdkDetails": {
+ "type": "object",
+ "properties": {
+ "package": {
+ "type": "string"
+ },
+ "cdn": {
+ "type": "string",
+ "format": "uri"
+ },
+ "cdnRequired": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "Theming": {
+ "type": "object",
+ "properties": {
+ "system": {
+ "type": "string"
+ },
+ "prebuiltThemes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "customizable": {
+ "type": "boolean"
+ },
+ "variables": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "Communication": {
+ "type": "object",
+ "properties": {
+ "pattern": {
+ "type": "string",
+ "enum": [
+ "callbacks",
+ "events",
+ "promises",
+ "observables"
+ ]
+ },
+ "events": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "JsSdkConfig": {
+ "type": "object",
+ "properties": {
+ "globalObject": {
+ "type": "string"
+ },
+ "package": {
+ "type": "string"
+ },
+ "cdn": {
+ "type": "string",
+ "format": "uri"
+ },
+ "initialization": {
+ "$ref": "#/$defs/Initialization"
+ },
+ "namespaces": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/Namespace"
+ }
+ },
+ "capabilities": {
+ "$ref": "#/$defs/SdkCapabilities"
+ },
+ "asyncPattern": {
+ "type": "string",
+ "enum": [
+ "promises",
+ "callbacks",
+ "observables",
+ "sync"
+ ]
+ }
+ }
+ },
+ "Initialization": {
+ "type": "object",
+ "properties": {
+ "method": {
+ "type": "string"
+ },
+ "async": {
+ "type": "boolean"
+ }
+ }
+ },
+ "Namespace": {
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string"
+ },
+ "methods": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "SdkCapabilities": {
+ "type": "object",
+ "properties": {
+ "context": {
+ "type": "boolean"
+ },
+ "uiActions": {
+ "type": "boolean"
+ },
+ "dataActions": {
+ "type": "boolean"
+ },
+ "events": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+}
diff --git a/specs/fenestra/schemas/extensions/agents/v0.1/fenestra-agents.schema.json b/specs/fenestra/schemas/extensions/agents/v0.1/fenestra-agents.schema.json
new file mode 100644
index 0000000..3de1303
--- /dev/null
+++ b/specs/fenestra/schemas/extensions/agents/v0.1/fenestra-agents.schema.json
@@ -0,0 +1,448 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://spec.openapis.org/fenestra/extensions/agents/v0.1/schema.json",
+ "title": "Fenestra Agents Extension Schema",
+ "description": "JSON Schema for validating Fenestra Agent Interaction extension documents describing how AI agents interact with platform UI",
+ "type": "object",
+ "$ref": "#/$defs/AgentInteraction",
+ "$defs": {
+ "AgentInteraction": {
+ "type": "object",
+ "properties": {
+ "capabilities": {
+ "$ref": "#/$defs/AgentCapabilitiesSummary"
+ },
+ "protocols": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/AgentProtocol"
+ }
+ },
+ "discovery": {
+ "$ref": "#/$defs/AgentDiscovery"
+ },
+ "context": {
+ "$ref": "#/$defs/AgentContext"
+ },
+ "uiInvocation": {
+ "$ref": "#/$defs/UIInvocation"
+ },
+ "events": {
+ "$ref": "#/$defs/AgentEvents"
+ },
+ "permissions": {
+ "$ref": "#/$defs/AgentPermissions"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "description": "Specification extension"
+ }
+ }
+ },
+ "AgentCapabilitiesSummary": {
+ "type": "object",
+ "description": "High-level agent interaction capabilities",
+ "properties": {
+ "templateInvocation": {
+ "type": "boolean",
+ "description": "Agent can invoke pre-defined UI templates"
+ },
+ "customUISupport": {
+ "type": "boolean",
+ "description": "Agent can open custom UI (iframe)"
+ },
+ "eventCallbacks": {
+ "type": "boolean",
+ "description": "Agent can receive UI events"
+ },
+ "actionChaining": {
+ "type": "boolean",
+ "description": "Agent can chain multiple UI interactions"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "description": "Specification extension"
+ }
+ }
+ },
+ "AgentProtocol": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "description": "A supported agent protocol",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Protocol name (e.g., mcp, openai-functions, anthropic-tools, langchain-tools, custom)"
+ },
+ "version": {
+ "type": "string",
+ "description": "Protocol version"
+ },
+ "package": {
+ "type": "string",
+ "description": "Package providing the protocol implementation"
+ },
+ "schemaFormat": {
+ "type": "string",
+ "enum": [
+ "openapi",
+ "jsonSchema",
+ "custom"
+ ],
+ "description": "Schema format for function/tool definitions"
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri",
+ "description": "URI to protocol documentation"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "description": "Specification extension"
+ }
+ }
+ },
+ "AgentDiscovery": {
+ "type": "object",
+ "description": "How agents discover UI capabilities",
+ "properties": {
+ "templateDiscovery": {
+ "type": "boolean",
+ "description": "Agent can query available UI templates"
+ },
+ "actionDiscovery": {
+ "type": "boolean",
+ "description": "Agent can query available actions"
+ },
+ "manifest": {
+ "type": "string",
+ "format": "uri",
+ "description": "URI to agent UI manifest/schema"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "description": "Specification extension"
+ }
+ }
+ },
+ "AgentContext": {
+ "type": "object",
+ "description": "Context passing to agents",
+ "properties": {
+ "available": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Available context types (e.g., conversationHistory, userIdentity, currentDocument)"
+ },
+ "format": {
+ "type": "string",
+ "default": "json",
+ "description": "Serialization format"
+ },
+ "piiFiltering": {
+ "type": "string",
+ "enum": [
+ "automatic",
+ "manual",
+ "none"
+ ],
+ "description": "PII filtering mode"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "description": "Specification extension"
+ }
+ }
+ },
+ "UIInvocation": {
+ "type": "object",
+ "description": "How agents invoke UI",
+ "properties": {
+ "methods": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Available invocation methods (e.g., templates, customIframe, deepLinks)"
+ },
+ "chainingSupported": {
+ "type": "boolean",
+ "description": "Whether chaining multiple interactions is supported"
+ },
+ "interactionTimeout": {
+ "type": "integer",
+ "description": "Timeout for interactions in seconds"
+ },
+ "cancellationSupported": {
+ "type": "boolean",
+ "description": "Whether interactions can be cancelled"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "description": "Specification extension"
+ }
+ }
+ },
+ "AgentEvents": {
+ "type": "object",
+ "description": "Events sent back to agents",
+ "properties": {
+ "supported": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Supported event types (e.g., formSubmitted, actionClicked, uiDismissed, errorOccurred)"
+ },
+ "delivery": {
+ "type": "string",
+ "enum": [
+ "callback",
+ "webhook",
+ "polling"
+ ],
+ "description": "Event delivery method"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "description": "Specification extension"
+ }
+ }
+ },
+ "AgentPermissions": {
+ "type": "object",
+ "description": "Agent permission model",
+ "properties": {
+ "canInvokeTemplates": {
+ "type": "boolean",
+ "description": "Agent can invoke UI templates"
+ },
+ "canOpenCustomUI": {
+ "type": "boolean",
+ "description": "Agent can open custom UI"
+ },
+ "canAccessUserData": {
+ "type": "boolean",
+ "description": "Agent can access user data"
+ },
+ "canPerformActions": {
+ "type": "boolean",
+ "description": "Agent can perform actions (not just show UI)"
+ },
+ "userApprovalRequired": {
+ "$ref": "#/$defs/UserApproval"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "description": "Specification extension"
+ }
+ }
+ },
+ "UserApproval": {
+ "type": "object",
+ "description": "When user approval is required",
+ "properties": {
+ "forActions": {
+ "type": "boolean",
+ "description": "User must approve actions"
+ },
+ "forDataAccess": {
+ "type": "boolean",
+ "description": "User must approve data access"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "description": "Specification extension"
+ }
+ }
+ },
+ "AgentTemplates": {
+ "type": "object",
+ "properties": {
+ "supported": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "definitions": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/AgentUITemplate"
+ }
+ }
+ }
+ },
+ "AgentUITemplate": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "inputSchema": {
+ "type": "object"
+ },
+ "outputSchema": {
+ "type": "object"
+ },
+ "rendering": {
+ "$ref": "#/$defs/TemplateRendering"
+ },
+ "interactivity": {
+ "$ref": "#/$defs/TemplateInteractivity"
+ }
+ }
+ },
+ "TemplateRendering": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "platform",
+ "jsonForms",
+ "custom"
+ ]
+ },
+ "component": {
+ "type": "string"
+ }
+ }
+ },
+ "TemplateInteractivity": {
+ "type": "object",
+ "properties": {
+ "submitButton": {
+ "type": "boolean"
+ },
+ "cancelButton": {
+ "type": "boolean"
+ },
+ "events": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "CustomUI": {
+ "type": "object",
+ "properties": {
+ "allowed": {
+ "type": "boolean",
+ "default": true
+ },
+ "sandboxAttributes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sizeConstraints": {
+ "$ref": "#/$defs/SizeConstraints"
+ }
+ }
+ },
+ "SizeConstraints": {
+ "type": "object",
+ "properties": {
+ "minWidth": {
+ "type": "integer"
+ },
+ "maxWidth": {
+ "type": "integer"
+ },
+ "minHeight": {
+ "type": "integer"
+ },
+ "maxHeight": {
+ "type": "integer"
+ },
+ "resizable": {
+ "type": "boolean"
+ }
+ }
+ },
+ "AgentCommunication": {
+ "type": "object",
+ "properties": {
+ "protocol": {
+ "type": "string",
+ "enum": [
+ "jsonRpc",
+ "postMessage",
+ "mcp"
+ ],
+ "default": "jsonRpc"
+ },
+ "channels": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "AgentCapabilities": {
+ "type": "object",
+ "properties": {
+ "invokeTemplates": {
+ "type": "boolean",
+ "default": true
+ },
+ "openCustomUI": {
+ "type": "boolean",
+ "default": true
+ },
+ "receiveEvents": {
+ "type": "boolean",
+ "default": true
+ },
+ "closeUI": {
+ "type": "boolean",
+ "default": true
+ },
+ "chainInteractions": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "AgentUIConfig": {
+ "type": "object",
+ "description": "Configuration for agentUI extension type",
+ "additionalProperties": false,
+ "properties": {
+ "templates": {
+ "$ref": "#/$defs/AgentTemplates"
+ },
+ "customUI": {
+ "$ref": "#/$defs/CustomUI"
+ },
+ "communication": {
+ "$ref": "#/$defs/AgentCommunication"
+ },
+ "agentCapabilities": {
+ "$ref": "#/$defs/AgentCapabilities"
+ }
+ }
+ }
+ }
+}
diff --git a/specs/fenestra/schemas/extensions/compliance/v0.1/fenestra-compliance.schema.json b/specs/fenestra/schemas/extensions/compliance/v0.1/fenestra-compliance.schema.json
new file mode 100644
index 0000000..46d7b1f
--- /dev/null
+++ b/specs/fenestra/schemas/extensions/compliance/v0.1/fenestra-compliance.schema.json
@@ -0,0 +1,281 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://spec.openapis.org/fenestra/extensions/compliance/v0.1/schema.json",
+ "title": "Fenestra Compliance Extension Schema",
+ "description": "JSON Schema for validating Fenestra Compliance extension documents describing accessibility, security, and privacy requirements",
+ "type": "object",
+ "$ref": "#/$defs/Compliance",
+ "$defs": {
+ "Compliance": {
+ "type": "object",
+ "properties": {
+ "accessibility": {
+ "$ref": "#/$defs/AccessibilityCompliance"
+ },
+ "security": {
+ "$ref": "#/$defs/SecurityCompliance"
+ },
+ "privacy": {
+ "$ref": "#/$defs/PrivacyCompliance"
+ },
+ "sharedResponsibility": {
+ "$ref": "#/$defs/SharedResponsibility"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "description": "Specification extension"
+ }
+ }
+ },
+ "AccessibilityCompliance": {
+ "type": "object",
+ "properties": {
+ "platformStandard": {
+ "type": "string"
+ },
+ "extensionRequirements": {
+ "$ref": "#/$defs/AccessibilityExtensionRequirements"
+ },
+ "platformProvides": {
+ "$ref": "#/$defs/PlatformAccessibility"
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri"
+ }
+ }
+ },
+ "AccessibilityExtensionRequirements": {
+ "type": "object",
+ "properties": {
+ "standard": {
+ "type": "string",
+ "enum": [
+ "none",
+ "WCAG 2.0 A",
+ "WCAG 2.0 AA",
+ "WCAG 2.1 A",
+ "WCAG 2.1 AA",
+ "WCAG 2.2 AA",
+ "Section 508"
+ ]
+ },
+ "scope": {
+ "type": "string",
+ "enum": [
+ "all",
+ "marketplace",
+ "public",
+ "none"
+ ]
+ },
+ "auditRequired": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "PlatformAccessibility": {
+ "type": "object",
+ "properties": {
+ "accessibleComponents": {
+ "type": "boolean"
+ },
+ "screenReaderTested": {
+ "type": "boolean"
+ },
+ "keyboardNavigation": {
+ "type": "boolean"
+ },
+ "focusManagement": {
+ "type": "boolean"
+ },
+ "ariaAttributesHandled": {
+ "type": "boolean"
+ }
+ }
+ },
+ "SecurityCompliance": {
+ "type": "object",
+ "properties": {
+ "platformCertifications": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extensionRequirements": {
+ "$ref": "#/$defs/SecurityExtensionRequirements"
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri"
+ }
+ }
+ },
+ "SecurityExtensionRequirements": {
+ "type": "object",
+ "properties": {
+ "httpsOnly": {
+ "type": "boolean",
+ "default": true
+ },
+ "cspCompliance": {
+ "type": "boolean"
+ },
+ "noInlineScripts": {
+ "type": "boolean"
+ },
+ "noExternalScripts": {
+ "type": "boolean",
+ "default": false
+ },
+ "securityReview": {
+ "$ref": "#/$defs/ReviewRequirement"
+ },
+ "dataHandling": {
+ "$ref": "#/$defs/DataHandling"
+ }
+ }
+ },
+ "ReviewRequirement": {
+ "type": "object",
+ "properties": {
+ "required": {
+ "type": "boolean"
+ },
+ "scope": {
+ "type": "string",
+ "enum": [
+ "all",
+ "marketplace",
+ "public",
+ "none"
+ ]
+ }
+ }
+ },
+ "DataHandling": {
+ "type": "object",
+ "properties": {
+ "piiAllowed": {
+ "type": "boolean"
+ },
+ "piiMustEncrypt": {
+ "type": "boolean"
+ },
+ "dataRetentionPolicy": {
+ "type": "string",
+ "enum": [
+ "required",
+ "recommended",
+ "none"
+ ]
+ }
+ }
+ },
+ "PrivacyCompliance": {
+ "type": "object",
+ "properties": {
+ "platformCompliance": {
+ "$ref": "#/$defs/PlatformPrivacy"
+ },
+ "dataResidency": {
+ "$ref": "#/$defs/DataResidency"
+ },
+ "extensionRequirements": {
+ "$ref": "#/$defs/PrivacyExtensionRequirements"
+ },
+ "userRights": {
+ "$ref": "#/$defs/UserRights"
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri"
+ }
+ }
+ },
+ "PlatformPrivacy": {
+ "type": "object",
+ "properties": {
+ "gdpr": {
+ "type": "boolean"
+ },
+ "ccpa": {
+ "type": "boolean"
+ }
+ }
+ },
+ "DataResidency": {
+ "type": "object",
+ "properties": {
+ "available": {
+ "type": "boolean"
+ },
+ "regions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "PrivacyExtensionRequirements": {
+ "type": "object",
+ "properties": {
+ "privacyPolicyRequired": {
+ "type": "boolean"
+ },
+ "consentManagement": {
+ "type": "string",
+ "enum": [
+ "platform",
+ "developer",
+ "both"
+ ]
+ },
+ "dataProcessingAgreement": {
+ "type": "string",
+ "enum": [
+ "required",
+ "recommended",
+ "none"
+ ]
+ }
+ }
+ },
+ "UserRights": {
+ "type": "object",
+ "properties": {
+ "dataExportSupported": {
+ "type": "boolean"
+ },
+ "dataDeletionSupported": {
+ "type": "boolean"
+ }
+ }
+ },
+ "SharedResponsibility": {
+ "type": "object",
+ "properties": {
+ "platformHandles": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "developerHandles": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri"
+ }
+ }
+ }
+ }
+}
diff --git a/specs/fenestra/schemas/extensions/declarative/v0.1/fenestra-declarative.schema.json b/specs/fenestra/schemas/extensions/declarative/v0.1/fenestra-declarative.schema.json
new file mode 100644
index 0000000..8d8b3de
--- /dev/null
+++ b/specs/fenestra/schemas/extensions/declarative/v0.1/fenestra-declarative.schema.json
@@ -0,0 +1,89 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://spec.openapis.org/fenestra/extensions/declarative/v0.1/schema.json",
+ "title": "Fenestra Declarative Schema Extension",
+ "description": "JSON Schema for validating Fenestra Declarative Schema extension documents describing declarative UI schemas like Block Kit and Adaptive Cards",
+ "type": "object",
+ "$ref": "#/$defs/DeclarativeSchema",
+ "$defs": {
+ "DeclarativeSchema": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "schemaUrl": {
+ "type": "string",
+ "format": "uri"
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri"
+ },
+ "delivery": {
+ "$ref": "#/$defs/Delivery"
+ },
+ "elementMappings": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/ElementMapping"
+ }
+ },
+ "validator": {
+ "$ref": "#/$defs/ValidatorTool"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "description": "Specification extension"
+ }
+ }
+ },
+ "Delivery": {
+ "type": "object",
+ "properties": {
+ "method": {
+ "type": "string",
+ "enum": [
+ "httpResponse",
+ "webhook",
+ "websocket"
+ ]
+ },
+ "contentType": {
+ "type": "string",
+ "default": "application/json"
+ }
+ }
+ },
+ "ElementMapping": {
+ "type": "object",
+ "properties": {
+ "fenestraComponent": {
+ "type": "string"
+ },
+ "notes": {
+ "type": "string"
+ }
+ }
+ },
+ "ValidatorTool": {
+ "type": "object",
+ "properties": {
+ "tool": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ }
+ }
+ }
+ }
+}
diff --git a/specs/fenestra/schemas/extensions/i18n/v0.1/fenestra-i18n.schema.json b/specs/fenestra/schemas/extensions/i18n/v0.1/fenestra-i18n.schema.json
new file mode 100644
index 0000000..c73ca05
--- /dev/null
+++ b/specs/fenestra/schemas/extensions/i18n/v0.1/fenestra-i18n.schema.json
@@ -0,0 +1,181 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://spec.openapis.org/fenestra/extensions/i18n/v0.1/schema.json",
+ "title": "Fenestra I18n Extension Schema",
+ "description": "JSON Schema for validating Fenestra I18n extension documents describing internationalization and localization capabilities",
+ "type": "object",
+ "$ref": "#/$defs/I18n",
+ "$defs": {
+ "I18n": {
+ "type": "object",
+ "properties": {
+ "platformSupport": {
+ "$ref": "#/$defs/I18nPlatformSupport"
+ },
+ "componentTranslations": {
+ "$ref": "#/$defs/ComponentTranslations"
+ },
+ "developerRequirements": {
+ "$ref": "#/$defs/I18nDeveloperRequirements"
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri"
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "description": "Specification extension"
+ }
+ }
+ },
+ "I18nPlatformSupport": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "default": false
+ },
+ "availableLocales": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "localeDetection": {
+ "$ref": "#/$defs/LocaleDetection"
+ },
+ "rtlSupport": {
+ "$ref": "#/$defs/RtlSupport"
+ }
+ }
+ },
+ "LocaleDetection": {
+ "type": "object",
+ "properties": {
+ "method": {
+ "type": "string",
+ "enum": [
+ "automatic",
+ "manual",
+ "both"
+ ]
+ },
+ "sources": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "RtlSupport": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "default": false
+ },
+ "languages": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "ComponentTranslations": {
+ "type": "object",
+ "properties": {
+ "provided": {
+ "type": "boolean"
+ },
+ "scope": {
+ "type": "string",
+ "enum": [
+ "all",
+ "partial",
+ "none"
+ ]
+ }
+ }
+ },
+ "I18nDeveloperRequirements": {
+ "type": "object",
+ "properties": {
+ "translationMechanism": {
+ "$ref": "#/$defs/TranslationMechanism"
+ },
+ "marketplaceRequirement": {
+ "$ref": "#/$defs/MarketplaceI18nRequirement"
+ },
+ "formatting": {
+ "$ref": "#/$defs/Formatting"
+ }
+ }
+ },
+ "TranslationMechanism": {
+ "type": "object",
+ "properties": {
+ "format": {
+ "type": "string",
+ "enum": [
+ "icu",
+ "i18next",
+ "gettext",
+ "json",
+ "custom"
+ ]
+ },
+ "bundleLocation": {
+ "type": "string",
+ "enum": [
+ "embedded",
+ "remote",
+ "platform-hosted"
+ ]
+ }
+ }
+ },
+ "MarketplaceI18nRequirement": {
+ "type": "object",
+ "properties": {
+ "required": {
+ "type": "boolean"
+ },
+ "minimumLocales": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "Formatting": {
+ "type": "object",
+ "properties": {
+ "dates": {
+ "type": "string",
+ "enum": [
+ "platform",
+ "developer"
+ ]
+ },
+ "numbers": {
+ "type": "string",
+ "enum": [
+ "platform",
+ "developer"
+ ]
+ },
+ "currencies": {
+ "type": "string",
+ "enum": [
+ "platform",
+ "developer"
+ ]
+ }
+ }
+ }
+ }
+}
diff --git a/specs/fenestra/tools/README.md b/specs/fenestra/tools/README.md
new file mode 100644
index 0000000..d738979
--- /dev/null
+++ b/specs/fenestra/tools/README.md
@@ -0,0 +1,93 @@
+# Fenestra CLI Tools
+
+Command-line tools for working with the Fenestra Specification.
+
+## Installation
+
+```bash
+# From npm (when published)
+npm install -g @fenestra/cli
+
+# From source
+cd tools
+npm install
+npm link
+```
+
+## Commands
+
+### validate
+
+Validate a Fenestra document against the specification schema.
+
+```bash
+fenestra validate
+```
+
+**Options:**
+- `-s, --schema ` - Use a custom schema file
+- `-q, --quiet` - Only output errors
+- `--json` - Output results as JSON
+
+**Examples:**
+
+```bash
+# Validate a Fenestra document
+fenestra validate ./hubspot.fenestra.yaml
+
+# Output:
+# Validating: /path/to/hubspot.fenestra.yaml
+#
+# Document Info:
+# Title: HubSpot UI Extensions
+# Version: 1.0.0
+# Fenestra: 0.1.0
+# Platform: HubSpot
+#
+# ℹ 25 component(s) defined
+# ℹ 3 extension point(s)
+# ℹ 2 SDK(s) defined
+# ℹ Policies: components: required, custom: not allowed
+#
+# ✓ Valid Fenestra document
+# Contains: 25 components, 3 extension points, 2 SDKs
+
+# Quiet mode (only errors)
+fenestra validate ./my-app.yaml --quiet
+
+# JSON output for CI/CD
+fenestra validate ./my-app.yaml --json
+
+# Use custom schema
+fenestra validate ./my-app.yaml --schema ./custom-schema.json
+```
+
+**Exit Codes:**
+- `0` - Document is valid
+- `1` - Document is invalid or error occurred
+
+## Validation Checks
+
+The validator performs:
+
+1. **Schema Validation** - Validates against JSON Schema Draft 2020-12
+2. **Reference Checking** - Verifies SDK references in components exist
+3. **Completeness Warnings** - Warns about missing recommended fields
+4. **Extension Type Validation** - Checks valid extension types
+
+## Development
+
+```bash
+# Install dependencies
+npm install
+
+# Run tests
+npm test
+
+# Run validator directly
+node bin/fenestra.js validate ../examples/0.1.0/hubspot.fenestra.yaml
+```
+
+## License
+
+Apache-2.0
diff --git a/specs/fenestra/tools/bin/fenestra.js b/specs/fenestra/tools/bin/fenestra.js
new file mode 100644
index 0000000..08fabc6
--- /dev/null
+++ b/specs/fenestra/tools/bin/fenestra.js
@@ -0,0 +1,21 @@
+#!/usr/bin/env node
+
+import { Command } from 'commander';
+import { validateCommand } from '../lib/commands/validate.js';
+
+const program = new Command();
+
+program
+ .name('fenestra')
+ .description('CLI tools for the Fenestra Specification')
+ .version('0.1.0');
+
+program
+ .command('validate ')
+ .description('Validate a Fenestra document against the specification schema')
+ .option('-s, --schema ', 'Path to custom schema file')
+ .option('-q, --quiet', 'Only output errors')
+ .option('--json', 'Output results as JSON')
+ .action(validateCommand);
+
+program.parse();
diff --git a/specs/fenestra/tools/lib/commands/validate.js b/specs/fenestra/tools/lib/commands/validate.js
new file mode 100644
index 0000000..7a64df2
--- /dev/null
+++ b/specs/fenestra/tools/lib/commands/validate.js
@@ -0,0 +1,169 @@
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+import chalk from 'chalk';
+import { FenestraValidator } from '../validator.js';
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+
+export async function validateCommand(file, options) {
+ const results = {
+ file: path.resolve(file),
+ valid: false,
+ errors: [],
+ warnings: [],
+ info: []
+ };
+
+ try {
+ // Check file exists
+ if (!fs.existsSync(file)) {
+ results.errors.push({
+ type: 'file',
+ message: `File not found: ${file}`
+ });
+ outputResults(results, options);
+ process.exit(1);
+ }
+
+ // Determine schema path
+ let schemaPath = options.schema;
+ if (!schemaPath) {
+ // Default to bundled schema
+ schemaPath = path.resolve(__dirname, '../../schemas/fenestra.schema.json');
+
+ // Fallback to repo schema if bundled not found
+ if (!fs.existsSync(schemaPath)) {
+ schemaPath = path.resolve(__dirname, '../../../schemas/v0.1/fenestra.schema.json');
+ }
+ }
+
+ if (!fs.existsSync(schemaPath)) {
+ results.errors.push({
+ type: 'schema',
+ message: `Schema file not found: ${schemaPath}`
+ });
+ outputResults(results, options);
+ process.exit(1);
+ }
+
+ // Create validator and validate
+ const validator = new FenestraValidator(schemaPath);
+ const validationResult = await validator.validate(file);
+
+ results.valid = validationResult.valid;
+ results.errors = validationResult.errors || [];
+ results.warnings = validationResult.warnings || [];
+ results.info = validationResult.info || [];
+ results.document = validationResult.document;
+
+ outputResults(results, options);
+ process.exit(results.valid ? 0 : 1);
+
+ } catch (error) {
+ results.errors.push({
+ type: 'internal',
+ message: error.message
+ });
+ outputResults(results, options);
+ process.exit(1);
+ }
+}
+
+function outputResults(results, options) {
+ if (options.json) {
+ console.log(JSON.stringify(results, null, 2));
+ return;
+ }
+
+ const { valid, errors, warnings, info, file, document } = results;
+
+ if (!options.quiet) {
+ console.log();
+ console.log(chalk.bold(`Validating: ${file}`));
+ console.log();
+ }
+
+ // Show document info
+ if (document && !options.quiet) {
+ console.log(chalk.cyan('Document Info:'));
+ console.log(` Title: ${document.info?.title || 'N/A'}`);
+ console.log(` Version: ${document.info?.version || 'N/A'}`);
+ console.log(` Fenestra: ${document.fenestra || 'N/A'}`);
+ if (document.platform?.name) {
+ console.log(` Platform: ${document.platform.name}`);
+ }
+ console.log();
+ }
+
+ // Show info messages
+ if (info.length > 0 && !options.quiet) {
+ for (const item of info) {
+ console.log(chalk.blue(`ℹ ${item.message}`));
+ if (item.details) {
+ console.log(chalk.gray(` ${item.details}`));
+ }
+ }
+ console.log();
+ }
+
+ // Show warnings
+ if (warnings.length > 0) {
+ for (const warning of warnings) {
+ console.log(chalk.yellow(`⚠ Warning: ${warning.message}`));
+ if (warning.path) {
+ console.log(chalk.gray(` Path: ${warning.path}`));
+ }
+ if (warning.suggestion) {
+ console.log(chalk.gray(` Suggestion: ${warning.suggestion}`));
+ }
+ }
+ console.log();
+ }
+
+ // Show errors
+ if (errors.length > 0) {
+ for (const error of errors) {
+ console.log(chalk.red(`✗ Error: ${error.message}`));
+ if (error.path) {
+ console.log(chalk.gray(` Path: ${error.path}`));
+ }
+ if (error.keyword) {
+ console.log(chalk.gray(` Rule: ${error.keyword}`));
+ }
+ if (error.params) {
+ console.log(chalk.gray(` Details: ${JSON.stringify(error.params)}`));
+ }
+ }
+ console.log();
+ }
+
+ // Summary
+ if (valid) {
+ console.log(chalk.green.bold('✓ Valid Fenestra document'));
+ if (!options.quiet) {
+ const stats = [];
+ if (results.document?.componentCatalog?.components) {
+ const count = Object.keys(results.document.componentCatalog.components).length;
+ stats.push(`${count} components`);
+ }
+ if (results.document?.extensionPoints) {
+ stats.push(`${results.document.extensionPoints.length} extension points`);
+ }
+ if (results.document?.sdks) {
+ stats.push(`${Object.keys(results.document.sdks).length} SDKs`);
+ }
+ if (stats.length > 0) {
+ console.log(chalk.gray(` Contains: ${stats.join(', ')}`));
+ }
+ }
+ } else {
+ console.log(chalk.red.bold(`✗ Invalid: ${errors.length} error(s) found`));
+ }
+
+ if (warnings.length > 0) {
+ console.log(chalk.yellow(` ${warnings.length} warning(s)`));
+ }
+
+ console.log();
+}
diff --git a/specs/fenestra/tools/lib/validator.js b/specs/fenestra/tools/lib/validator.js
new file mode 100644
index 0000000..f3e50c6
--- /dev/null
+++ b/specs/fenestra/tools/lib/validator.js
@@ -0,0 +1,243 @@
+import fs from 'fs';
+import path from 'path';
+import Ajv from 'ajv';
+import addFormats from 'ajv-formats';
+import YAML from 'yaml';
+
+export class FenestraValidator {
+ constructor(schemaPath) {
+ this.schemaPath = schemaPath;
+ this.schema = JSON.parse(fs.readFileSync(schemaPath, 'utf-8'));
+
+ // Initialize AJV with JSON Schema Draft 2020-12 support
+ this.ajv = new Ajv({
+ allErrors: true,
+ verbose: true,
+ strict: false
+ });
+
+ // Add format validators (uri, email, etc.)
+ addFormats(this.ajv);
+
+ // Compile schema
+ this.validate_schema = this.ajv.compile(this.schema);
+ }
+
+ async validate(filePath) {
+ const result = {
+ valid: false,
+ errors: [],
+ warnings: [],
+ info: [],
+ document: null
+ };
+
+ try {
+ // Read and parse file
+ const content = fs.readFileSync(filePath, 'utf-8');
+ const ext = path.extname(filePath).toLowerCase();
+
+ let document;
+ try {
+ if (ext === '.json') {
+ document = JSON.parse(content);
+ } else if (ext === '.yaml' || ext === '.yml') {
+ document = YAML.parse(content);
+ } else {
+ // Try YAML first (more permissive), then JSON
+ try {
+ document = YAML.parse(content);
+ } catch {
+ document = JSON.parse(content);
+ }
+ }
+ } catch (parseError) {
+ result.errors.push({
+ type: 'parse',
+ message: `Failed to parse file: ${parseError.message}`
+ });
+ return result;
+ }
+
+ result.document = document;
+
+ // Schema validation
+ const schemaValid = this.validate_schema(document);
+
+ if (!schemaValid) {
+ for (const error of this.validate_schema.errors || []) {
+ result.errors.push({
+ type: 'schema',
+ message: error.message || 'Schema validation failed',
+ path: error.instancePath || '/',
+ keyword: error.keyword,
+ params: error.params
+ });
+ }
+ }
+
+ // Additional semantic validations
+ this.validateSemantics(document, result);
+
+ // Collect info
+ this.collectInfo(document, result);
+
+ // Determine overall validity
+ result.valid = result.errors.length === 0;
+
+ return result;
+
+ } catch (error) {
+ result.errors.push({
+ type: 'internal',
+ message: `Validation error: ${error.message}`
+ });
+ return result;
+ }
+ }
+
+ validateSemantics(document, result) {
+ // Check fenestra version
+ if (document.fenestra) {
+ const version = document.fenestra;
+ if (!version.match(/^0\.1\./)) {
+ result.warnings.push({
+ type: 'version',
+ message: `Fenestra version ${version} may not be fully supported`,
+ suggestion: 'Use version 0.1.x for compatibility'
+ });
+ }
+ }
+
+ // Check SDK references in components
+ if (document.componentCatalog?.components && document.sdks) {
+ const sdkIds = new Set(Object.keys(document.sdks));
+
+ for (const [componentId, component] of Object.entries(document.componentCatalog.components)) {
+ if (component.sdkBinding?.sdk) {
+ if (!sdkIds.has(component.sdkBinding.sdk)) {
+ result.errors.push({
+ type: 'reference',
+ message: `Component '${componentId}' references undefined SDK '${component.sdkBinding.sdk}'`,
+ path: `/componentCatalog/components/${componentId}/sdkBinding/sdk`
+ });
+ }
+ }
+ }
+ }
+
+ // Check extension point SDK references
+ if (document.extensionPoints && document.sdks) {
+ const sdkIds = new Set(Object.keys(document.sdks));
+
+ for (let i = 0; i < document.extensionPoints.length; i++) {
+ const ep = document.extensionPoints[i];
+ const config = ep.extensionTypeConfig;
+
+ if (config?.sdk && typeof config.sdk === 'string') {
+ if (!sdkIds.has(config.sdk)) {
+ result.warnings.push({
+ type: 'reference',
+ message: `Extension point '${ep.id}' references SDK '${config.sdk}' not defined in sdks`,
+ path: `/extensionPoints/${i}/extensionTypeConfig/sdk`
+ });
+ }
+ }
+ }
+ }
+
+ // Warn about missing recommended fields
+ if (!document.platform) {
+ result.warnings.push({
+ type: 'completeness',
+ message: 'No platform object defined',
+ suggestion: 'Add platform info for better documentation'
+ });
+ }
+
+ if (!document.sdks || Object.keys(document.sdks).length === 0) {
+ result.warnings.push({
+ type: 'completeness',
+ message: 'No SDKs defined',
+ suggestion: 'Add SDK definitions for component bindings'
+ });
+ }
+
+ if (!document.extensionPoints || document.extensionPoints.length === 0) {
+ result.warnings.push({
+ type: 'completeness',
+ message: 'No extension points defined',
+ suggestion: 'Add extension points to describe where UI can be injected'
+ });
+ }
+
+ // Check for extension type consistency
+ if (document.extensionPoints) {
+ const validTypes = ['jsonResponse', 'codedComponents', 'iframe', 'embeddedSdk', 'agentUI'];
+ for (const ep of document.extensionPoints) {
+ if (ep.extensionType && !validTypes.includes(ep.extensionType)) {
+ result.warnings.push({
+ type: 'enum',
+ message: `Extension point '${ep.id}' has unknown extensionType '${ep.extensionType}'`,
+ suggestion: `Valid types: ${validTypes.join(', ')}`
+ });
+ }
+ }
+ }
+ }
+
+ collectInfo(document, result) {
+ // Component count
+ if (document.componentCatalog?.components) {
+ const count = Object.keys(document.componentCatalog.components).length;
+ result.info.push({
+ type: 'stats',
+ message: `${count} component(s) defined`
+ });
+ }
+
+ // Extension points
+ if (document.extensionPoints) {
+ const types = {};
+ for (const ep of document.extensionPoints) {
+ types[ep.extensionType] = (types[ep.extensionType] || 0) + 1;
+ }
+ const summary = Object.entries(types)
+ .map(([type, count]) => `${count} ${type}`)
+ .join(', ');
+ result.info.push({
+ type: 'stats',
+ message: `${document.extensionPoints.length} extension point(s)`,
+ details: summary
+ });
+ }
+
+ // SDKs
+ if (document.sdks) {
+ const count = Object.keys(document.sdks).length;
+ result.info.push({
+ type: 'stats',
+ message: `${count} SDK(s) defined`
+ });
+ }
+
+ // Policies
+ if (document.policies) {
+ const policies = [];
+ if (document.policies.componentRequirement?.level) {
+ policies.push(`components: ${document.policies.componentRequirement.level}`);
+ }
+ if (document.policies.customComponents?.allowed !== undefined) {
+ policies.push(`custom: ${document.policies.customComponents.allowed ? 'allowed' : 'not allowed'}`);
+ }
+ if (policies.length > 0) {
+ result.info.push({
+ type: 'policies',
+ message: `Policies: ${policies.join(', ')}`
+ });
+ }
+ }
+ }
+}
+
+export default FenestraValidator;
diff --git a/specs/fenestra/tools/package-lock.json b/specs/fenestra/tools/package-lock.json
new file mode 100644
index 0000000..a4dc467
--- /dev/null
+++ b/specs/fenestra/tools/package-lock.json
@@ -0,0 +1,152 @@
+{
+ "name": "@fenestra/cli",
+ "version": "0.1.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "@fenestra/cli",
+ "version": "0.1.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "ajv": "^8.17.1",
+ "ajv-formats": "^3.0.1",
+ "chalk": "^5.3.0",
+ "commander": "^12.1.0",
+ "yaml": "^2.6.1"
+ },
+ "bin": {
+ "fenestra": "bin/fenestra.js"
+ },
+ "devDependencies": {
+ "@types/node": "^22.0.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "22.19.3",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.3.tgz",
+ "integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "8.17.1",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
+ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
+ "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/chalk": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
+ "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/commander": {
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
+ "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "license": "MIT"
+ },
+ "node_modules/fast-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
+ "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "license": "MIT"
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/yaml": {
+ "version": "2.8.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
+ "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/eemeli"
+ }
+ }
+ }
+}
diff --git a/specs/fenestra/tools/package.json b/specs/fenestra/tools/package.json
new file mode 100644
index 0000000..00a01cf
--- /dev/null
+++ b/specs/fenestra/tools/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "@fenestra/cli",
+ "version": "0.1.0",
+ "description": "CLI tools for the Fenestra Specification",
+ "type": "module",
+ "bin": {
+ "fenestra": "./bin/fenestra.js"
+ },
+ "scripts": {
+ "validate": "node bin/fenestra.js validate",
+ "test": "node --test test/"
+ },
+ "keywords": [
+ "fenestra",
+ "openapi",
+ "ui-components",
+ "sdk",
+ "specification",
+ "validator"
+ ],
+ "author": "Fenestra Working Group",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "ajv": "^8.17.1",
+ "ajv-formats": "^3.0.1",
+ "chalk": "^5.3.0",
+ "commander": "^12.1.0",
+ "yaml": "^2.6.1"
+ },
+ "devDependencies": {
+ "@types/node": "^22.0.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/friggframework/fenestra-spec.git",
+ "directory": "tools"
+ }
+}
diff --git a/specs/fenestra/tools/schemas/fenestra.schema.json b/specs/fenestra/tools/schemas/fenestra.schema.json
new file mode 100644
index 0000000..53b433a
--- /dev/null
+++ b/specs/fenestra/tools/schemas/fenestra.schema.json
@@ -0,0 +1,1317 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://spec.openapis.org/fenestra/core/v0.1/schema.json",
+ "title": "Fenestra Core Specification Schema",
+ "description": "JSON Schema for validating Fenestra Core Description documents",
+ "type": "object",
+ "required": [
+ "fenestra",
+ "info"
+ ],
+ "properties": {
+ "fenestra": {
+ "type": "string",
+ "description": "Fenestra specification version",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+(-[a-zA-Z0-9]+)?$"
+ },
+ "info": {
+ "$ref": "#/$defs/Info"
+ },
+ "platform": {
+ "$ref": "#/$defs/Platform"
+ },
+ "sdks": {
+ "type": "object",
+ "description": "SDK ecosystem definitions indexed by SDK identifier",
+ "additionalProperties": {
+ "$ref": "#/$defs/SDK"
+ }
+ },
+ "componentCatalog": {
+ "$ref": "#/$defs/ComponentCatalog"
+ },
+ "renderingEngines": {
+ "type": "object",
+ "description": "Supported rendering engine configurations",
+ "additionalProperties": {
+ "$ref": "#/$defs/RenderingEngine"
+ }
+ },
+ "policies": {
+ "$ref": "#/$defs/Policies"
+ },
+ "extensionPoints": {
+ "type": "array",
+ "description": "Where UI can be injected in the host platform",
+ "items": {
+ "$ref": "#/$defs/ExtensionPoint"
+ }
+ }
+ },
+ "patternProperties": {
+ "^x-": {
+ "description": "Specification extension"
+ }
+ },
+ "$defs": {
+ "Info": {
+ "type": "object",
+ "required": [
+ "title",
+ "version"
+ ],
+ "properties": {
+ "title": {
+ "type": "string",
+ "description": "Human-readable title for the Fenestra Description"
+ },
+ "summary": {
+ "type": "string",
+ "description": "A short summary of the platform's UI capabilities"
+ },
+ "description": {
+ "type": "string",
+ "description": "Extended description (CommonMark supported)"
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of this Fenestra Description document"
+ },
+ "termsOfService": {
+ "type": "string",
+ "format": "uri"
+ },
+ "contact": {
+ "$ref": "#/$defs/Contact"
+ },
+ "license": {
+ "$ref": "#/$defs/License"
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "Contact": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ },
+ "email": {
+ "type": "string",
+ "format": "email"
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "License": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "identifier": {
+ "type": "string",
+ "description": "SPDX license expression"
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "Platform": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Platform name"
+ },
+ "vendor": {
+ "type": "string",
+ "description": "Platform vendor/company name"
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri",
+ "description": "URL to platform developer documentation"
+ },
+ "appMarketplace": {
+ "type": "string",
+ "format": "uri",
+ "description": "URL to the platform's app marketplace"
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "SDK": {
+ "type": "object",
+ "required": [
+ "name",
+ "packageManager",
+ "package"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Human-readable SDK name"
+ },
+ "packageManager": {
+ "type": "string",
+ "enum": [
+ "npm",
+ "yarn",
+ "pip",
+ "maven",
+ "gradle",
+ "nuget",
+ "cargo",
+ "go",
+ "composer",
+ "cocoapods",
+ "carthage",
+ "swift-package-manager"
+ ]
+ },
+ "package": {
+ "type": "string",
+ "description": "Package identifier"
+ },
+ "version": {
+ "type": "string",
+ "description": "Recommended or minimum version"
+ },
+ "platform": {
+ "type": "string",
+ "enum": [
+ "web",
+ "ios",
+ "android",
+ "react-native",
+ "flutter",
+ "electron"
+ ],
+ "default": "web",
+ "description": "Target platform"
+ },
+ "mobile": {
+ "$ref": "#/$defs/MobileSDK"
+ },
+ "repository": {
+ "type": "string",
+ "format": "uri"
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri"
+ },
+ "installCommand": {
+ "type": "string",
+ "description": "Full install command for quick setup"
+ },
+ "cdn": {
+ "type": "string",
+ "format": "uri",
+ "description": "CDN URL for script tag loading"
+ },
+ "cdnRequired": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether SDK must be loaded from CDN"
+ },
+ "typesPackage": {
+ "type": "string",
+ "description": "TypeScript types package if separate"
+ },
+ "starterTemplate": {
+ "$ref": "#/$defs/StarterTemplate"
+ },
+ "cliTool": {
+ "$ref": "#/$defs/CliTool"
+ },
+ "exports": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/SDKExport"
+ }
+ },
+ "subpackages": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/Subpackage"
+ }
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "StarterTemplate": {
+ "type": "object",
+ "properties": {
+ "command": {
+ "type": "string"
+ },
+ "repository": {
+ "type": "string",
+ "format": "uri"
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri"
+ }
+ }
+ },
+ "CliTool": {
+ "type": "object",
+ "properties": {
+ "package": {
+ "type": "string"
+ },
+ "installCommand": {
+ "type": "string"
+ },
+ "commands": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "SDKExport": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "component",
+ "hook",
+ "utility",
+ "icon",
+ "token",
+ "context",
+ "type"
+ ]
+ },
+ "description": {
+ "type": "string"
+ },
+ "deprecated": {
+ "type": "boolean",
+ "default": false
+ },
+ "since": {
+ "type": "string"
+ }
+ }
+ },
+ "Subpackage": {
+ "type": "object",
+ "properties": {
+ "package": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "exports": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/SDKExport"
+ }
+ }
+ }
+ },
+ "MobileSDK": {
+ "type": "object",
+ "description": "Mobile-specific SDK requirements",
+ "properties": {
+ "minOsVersion": {
+ "type": "string"
+ },
+ "targetOsVersion": {
+ "type": "string"
+ },
+ "capabilities": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "permissions": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "architectures": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "frameworks": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "appStoreGuidelines": {
+ "type": "string",
+ "format": "uri"
+ }
+ }
+ },
+ "ComponentCatalog": {
+ "type": "object",
+ "properties": {
+ "categories": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/ComponentCategory"
+ }
+ },
+ "components": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/Component"
+ }
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "ComponentCategory": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "components": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "Component": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "category": {
+ "type": "string"
+ },
+ "sdkBinding": {
+ "$ref": "#/$defs/SDKBinding"
+ },
+ "webStandardMapping": {
+ "$ref": "#/$defs/WebStandardMapping"
+ },
+ "props": {
+ "type": "object",
+ "description": "Component properties (JSON Schema format)"
+ },
+ "slots": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/Slot"
+ }
+ },
+ "events": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/ComponentEvent"
+ }
+ },
+ "variants": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "accessibility": {
+ "$ref": "#/$defs/Accessibility"
+ },
+ "examples": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/ComponentExample"
+ }
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "SDKBinding": {
+ "type": "object",
+ "required": [
+ "sdk",
+ "export"
+ ],
+ "properties": {
+ "sdk": {
+ "type": "string"
+ },
+ "subpackage": {
+ "type": "string"
+ },
+ "export": {
+ "type": "string"
+ },
+ "importPath": {
+ "type": "string"
+ }
+ }
+ },
+ "WebStandardMapping": {
+ "type": "object",
+ "properties": {
+ "htmlElement": {
+ "type": "string"
+ },
+ "ariaRole": {
+ "type": "string"
+ },
+ "webComponent": {
+ "type": "string"
+ },
+ "semanticType": {
+ "type": "string",
+ "enum": [
+ "action",
+ "input",
+ "display",
+ "layout",
+ "navigation",
+ "feedback",
+ "container"
+ ]
+ }
+ }
+ },
+ "Slot": {
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string"
+ },
+ "required": {
+ "type": "boolean",
+ "default": false
+ },
+ "accepts": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "ComponentEvent": {
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string"
+ },
+ "payload": {
+ "type": "object"
+ }
+ }
+ },
+ "Accessibility": {
+ "type": "object",
+ "properties": {
+ "keyboardSupport": {
+ "type": "boolean"
+ },
+ "screenReaderSupport": {
+ "type": "boolean"
+ },
+ "focusManagement": {
+ "type": "string"
+ },
+ "notes": {
+ "type": "string"
+ }
+ }
+ },
+ "ComponentExample": {
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "code": {
+ "type": "string"
+ },
+ "language": {
+ "type": "string",
+ "default": "jsx"
+ }
+ }
+ },
+ "RenderingEngine": {
+ "type": "object",
+ "required": [
+ "type"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "jsonForms",
+ "jsonSchema",
+ "mcpApps",
+ "react",
+ "webComponents",
+ "lwc",
+ "custom"
+ ]
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "schemaSupport": {
+ "$ref": "#/$defs/SchemaSupport"
+ },
+ "sandboxing": {
+ "$ref": "#/$defs/SandboxConfig"
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "SchemaSupport": {
+ "type": "object",
+ "properties": {
+ "dataSchema": {
+ "type": "string",
+ "enum": [
+ "jsonSchema",
+ "custom"
+ ]
+ },
+ "uiSchema": {
+ "type": "string",
+ "enum": [
+ "jsonFormsUISchema",
+ "mcpAppsTemplate",
+ "custom"
+ ]
+ },
+ "customRenderers": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "SandboxConfig": {
+ "type": "object",
+ "properties": {
+ "iframeSandbox": {
+ "type": "boolean"
+ },
+ "sandboxAttributes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "cspPolicy": {
+ "type": "string"
+ }
+ }
+ },
+ "Policies": {
+ "type": "object",
+ "properties": {
+ "componentRequirement": {
+ "$ref": "#/$defs/ComponentRequirementPolicy"
+ },
+ "customComponents": {
+ "$ref": "#/$defs/CustomComponentPolicy"
+ },
+ "publishing": {
+ "$ref": "#/$defs/PublishingPolicy"
+ },
+ "designGuidelines": {
+ "$ref": "#/$defs/DesignGuidelinesPolicy"
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "ComponentRequirementPolicy": {
+ "type": "object",
+ "properties": {
+ "level": {
+ "type": "string",
+ "enum": [
+ "required",
+ "recommended",
+ "optional"
+ ]
+ },
+ "scope": {
+ "type": "string",
+ "enum": [
+ "all",
+ "publicApps",
+ "marketplaceApps"
+ ]
+ },
+ "rationale": {
+ "type": "string"
+ },
+ "exceptions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "CustomComponentPolicy": {
+ "type": "object",
+ "properties": {
+ "allowed": {
+ "type": "boolean"
+ },
+ "constraints": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "mustWrapPlatformPrimitives",
+ "mustFollowDesignSystem",
+ "mustPassAccessibilityAudit",
+ "requiresReview",
+ "sandboxOnly"
+ ]
+ }
+ },
+ "registrationRequired": {
+ "type": "boolean",
+ "default": false
+ },
+ "approvalRequired": {
+ "type": "boolean",
+ "default": false
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri"
+ }
+ }
+ },
+ "PublishingPolicy": {
+ "type": "object",
+ "properties": {
+ "privateApps": {
+ "$ref": "#/$defs/AppPolicy"
+ },
+ "publicApps": {
+ "$ref": "#/$defs/AppPolicy"
+ },
+ "marketplaceApps": {
+ "$ref": "#/$defs/AppPolicy"
+ }
+ }
+ },
+ "AppPolicy": {
+ "type": "object",
+ "properties": {
+ "componentRequirement": {
+ "type": "string",
+ "enum": [
+ "required",
+ "recommended",
+ "optional"
+ ]
+ },
+ "customComponentsAllowed": {
+ "type": "boolean"
+ },
+ "reviewRequired": {
+ "type": "boolean"
+ },
+ "designReviewRequired": {
+ "type": "boolean"
+ },
+ "accessibilityAuditRequired": {
+ "type": "boolean"
+ },
+ "certificationRequired": {
+ "type": "boolean"
+ },
+ "notes": {
+ "type": "string"
+ }
+ }
+ },
+ "DesignGuidelinesPolicy": {
+ "type": "object",
+ "properties": {
+ "required": {
+ "type": "boolean"
+ },
+ "designSystem": {
+ "type": "string"
+ },
+ "designSystemUrl": {
+ "type": "string",
+ "format": "uri"
+ },
+ "designTokensProvided": {
+ "type": "boolean"
+ }
+ }
+ },
+ "ExtensionPoint": {
+ "type": "object",
+ "required": [
+ "id",
+ "name",
+ "type",
+ "extensionType"
+ ],
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "sidebar",
+ "modal",
+ "panel",
+ "card",
+ "toolbar",
+ "contextMenu",
+ "canvas",
+ "composer",
+ "fullPage",
+ "embedded"
+ ]
+ },
+ "extensionType": {
+ "type": "string",
+ "enum": [
+ "jsonResponse",
+ "codedComponents",
+ "iframe",
+ "embeddedSdk"
+ ]
+ },
+ "extensionTypeConfig": {
+ "type": "object",
+ "description": "Configuration specific to the extension type. Schema varies based on extensionType value."
+ },
+ "description": {
+ "type": "string"
+ },
+ "supportedComponents": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "constraints": {
+ "$ref": "#/$defs/Constraints"
+ },
+ "context": {
+ "$ref": "#/$defs/Context"
+ }
+ },
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "extensionType": {
+ "const": "jsonResponse"
+ }
+ },
+ "required": [
+ "extensionType"
+ ]
+ },
+ "then": {
+ "properties": {
+ "extensionTypeConfig": {
+ "$ref": "#/$defs/JsonResponseConfig"
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "extensionType": {
+ "const": "codedComponents"
+ }
+ },
+ "required": [
+ "extensionType"
+ ]
+ },
+ "then": {
+ "properties": {
+ "extensionTypeConfig": {
+ "$ref": "#/$defs/CodedComponentsConfig"
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "extensionType": {
+ "const": "iframe"
+ }
+ },
+ "required": [
+ "extensionType"
+ ]
+ },
+ "then": {
+ "properties": {
+ "extensionTypeConfig": {
+ "$ref": "#/$defs/IframeConfig"
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "extensionType": {
+ "const": "embeddedSdk"
+ }
+ },
+ "required": [
+ "extensionType"
+ ]
+ },
+ "then": {
+ "properties": {
+ "extensionTypeConfig": {
+ "$ref": "#/$defs/EmbeddedSdkConfig"
+ }
+ }
+ }
+ }
+ ],
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
+ "Constraints": {
+ "type": "object",
+ "properties": {
+ "maxWidth": {
+ "type": "integer"
+ },
+ "maxHeight": {
+ "type": "integer"
+ },
+ "responsive": {
+ "type": "boolean"
+ }
+ }
+ },
+ "Context": {
+ "type": "object",
+ "properties": {
+ "provides": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "actions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "JsonResponseConfig": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "schema": {
+ "$ref": "#/$defs/ResponseSchema"
+ },
+ "endpoint": {
+ "$ref": "#/$defs/Endpoint"
+ },
+ "interactivity": {
+ "$ref": "#/$defs/Interactivity"
+ }
+ }
+ },
+ "ResponseSchema": {
+ "type": "object",
+ "properties": {
+ "format": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "schemaUrl": {
+ "type": "string",
+ "format": "uri"
+ },
+ "encoding": {
+ "type": "string",
+ "default": "UTF-8"
+ }
+ }
+ },
+ "Endpoint": {
+ "type": "object",
+ "properties": {
+ "method": {
+ "type": "string",
+ "enum": [
+ "GET",
+ "POST"
+ ],
+ "default": "POST"
+ },
+ "contentType": {
+ "type": "string",
+ "default": "application/json"
+ },
+ "timeout": {
+ "type": "integer",
+ "default": 10
+ },
+ "authentication": {
+ "type": "string",
+ "enum": [
+ "none",
+ "oauth",
+ "jwt",
+ "signedRequest",
+ "apiKey"
+ ]
+ },
+ "contextProvided": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "Interactivity": {
+ "type": "object",
+ "properties": {
+ "callbackUrl": {
+ "type": "boolean"
+ },
+ "payloadTypes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "CodedComponentsConfig": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sdk": {
+ "type": "string"
+ },
+ "framework": {
+ "type": "string",
+ "enum": [
+ "react",
+ "vue",
+ "lwc",
+ "webComponents",
+ "agnostic"
+ ]
+ },
+ "runtime": {
+ "$ref": "#/$defs/Runtime"
+ },
+ "hostInteraction": {
+ "$ref": "#/$defs/JsSdkConfig"
+ }
+ }
+ },
+ "Runtime": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "sandboxedIframe",
+ "webWorker",
+ "directExecution"
+ ]
+ },
+ "bundling": {
+ "type": "string",
+ "enum": [
+ "platformBuild",
+ "developerBuild",
+ "cdn"
+ ]
+ }
+ }
+ },
+ "IframeConfig": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sandboxAttributes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "cspRequirements": {
+ "type": "string"
+ },
+ "sizeConstraints": {
+ "$ref": "#/$defs/SizeConstraints"
+ },
+ "communication": {
+ "$ref": "#/$defs/JsSdkConfig"
+ }
+ }
+ },
+ "SizeConstraints": {
+ "type": "object",
+ "properties": {
+ "minWidth": {
+ "type": "integer"
+ },
+ "maxWidth": {
+ "type": "integer"
+ },
+ "minHeight": {
+ "type": "integer"
+ },
+ "maxHeight": {
+ "type": "integer"
+ },
+ "resizable": {
+ "type": "boolean"
+ }
+ }
+ },
+ "EmbeddedSdkConfig": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sdk": {
+ "$ref": "#/$defs/EmbeddedSdkDetails"
+ },
+ "mountPattern": {
+ "type": "string",
+ "enum": [
+ "domSelector",
+ "reactComponent",
+ "webComponent",
+ "function"
+ ]
+ },
+ "theming": {
+ "$ref": "#/$defs/Theming"
+ },
+ "communication": {
+ "$ref": "#/$defs/Communication"
+ }
+ }
+ },
+ "EmbeddedSdkDetails": {
+ "type": "object",
+ "properties": {
+ "package": {
+ "type": "string"
+ },
+ "cdn": {
+ "type": "string",
+ "format": "uri"
+ },
+ "cdnRequired": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "Theming": {
+ "type": "object",
+ "properties": {
+ "system": {
+ "type": "string"
+ },
+ "prebuiltThemes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "customizable": {
+ "type": "boolean"
+ },
+ "variables": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "Communication": {
+ "type": "object",
+ "properties": {
+ "pattern": {
+ "type": "string",
+ "enum": [
+ "callbacks",
+ "events",
+ "promises",
+ "observables"
+ ]
+ },
+ "events": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "JsSdkConfig": {
+ "type": "object",
+ "properties": {
+ "globalObject": {
+ "type": "string"
+ },
+ "package": {
+ "type": "string"
+ },
+ "cdn": {
+ "type": "string",
+ "format": "uri"
+ },
+ "initialization": {
+ "$ref": "#/$defs/Initialization"
+ },
+ "namespaces": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/Namespace"
+ }
+ },
+ "capabilities": {
+ "$ref": "#/$defs/SdkCapabilities"
+ },
+ "asyncPattern": {
+ "type": "string",
+ "enum": [
+ "promises",
+ "callbacks",
+ "observables",
+ "sync"
+ ]
+ }
+ }
+ },
+ "Initialization": {
+ "type": "object",
+ "properties": {
+ "method": {
+ "type": "string"
+ },
+ "async": {
+ "type": "boolean"
+ }
+ }
+ },
+ "Namespace": {
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string"
+ },
+ "methods": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "SdkCapabilities": {
+ "type": "object",
+ "properties": {
+ "context": {
+ "type": "boolean"
+ },
+ "uiActions": {
+ "type": "boolean"
+ },
+ "dataActions": {
+ "type": "boolean"
+ },
+ "events": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+}
diff --git a/specs/fenestra/tools/test/validator.test.js b/specs/fenestra/tools/test/validator.test.js
new file mode 100644
index 0000000..6256ebd
--- /dev/null
+++ b/specs/fenestra/tools/test/validator.test.js
@@ -0,0 +1,106 @@
+import { test, describe } from 'node:test';
+import assert from 'node:assert';
+import path from 'path';
+import { fileURLToPath } from 'url';
+import { FenestraValidator } from '../lib/validator.js';
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const schemaPath = path.resolve(__dirname, '../schemas/fenestra.schema.json');
+const examplesPath = path.resolve(__dirname, '../../examples/0.1.0');
+
+describe('FenestraValidator', () => {
+ test('validates hubspot example', async () => {
+ const validator = new FenestraValidator(schemaPath);
+ const result = await validator.validate(path.join(examplesPath, 'hubspot.fenestra.yaml'));
+
+ console.log('HubSpot validation result:', result.valid);
+ if (!result.valid) {
+ console.log('Errors:', result.errors);
+ }
+
+ // Should be valid or have only minor schema differences
+ assert.ok(result.document, 'Document should be parsed');
+ assert.ok(result.document.fenestra, 'Should have fenestra version');
+ assert.ok(result.document.info, 'Should have info object');
+ });
+
+ test('validates miro example', async () => {
+ const validator = new FenestraValidator(schemaPath);
+ const result = await validator.validate(path.join(examplesPath, 'miro.fenestra.yaml'));
+
+ console.log('Miro validation result:', result.valid);
+ if (!result.valid) {
+ console.log('Errors:', result.errors);
+ }
+
+ assert.ok(result.document, 'Document should be parsed');
+ assert.ok(result.document.fenestra, 'Should have fenestra version');
+ });
+
+ test('validates mcp-apps example', async () => {
+ const validator = new FenestraValidator(schemaPath);
+ const result = await validator.validate(path.join(examplesPath, 'mcp-apps.fenestra.yaml'));
+
+ console.log('MCP Apps validation result:', result.valid);
+ if (!result.valid) {
+ console.log('Errors:', result.errors);
+ }
+
+ assert.ok(result.document, 'Document should be parsed');
+ });
+
+ test('detects missing required fields', async () => {
+ const validator = new FenestraValidator(schemaPath);
+
+ // Create a minimal invalid document
+ const invalidDoc = { fenestra: '0.1.0' }; // missing info
+
+ const tempPath = path.join(__dirname, 'temp-invalid.json');
+ const fs = await import('fs');
+ fs.writeFileSync(tempPath, JSON.stringify(invalidDoc));
+
+ try {
+ const result = await validator.validate(tempPath);
+ assert.strictEqual(result.valid, false, 'Should be invalid');
+ assert.ok(result.errors.length > 0, 'Should have errors');
+ } finally {
+ fs.unlinkSync(tempPath);
+ }
+ });
+
+ test('detects invalid SDK references', async () => {
+ const validator = new FenestraValidator(schemaPath);
+
+ const docWithBadRef = {
+ fenestra: '0.1.0',
+ info: { title: 'Test', version: '1.0.0' },
+ sdks: {
+ 'my-sdk': { name: 'My SDK', packageManager: 'npm', package: 'my-sdk' }
+ },
+ componentCatalog: {
+ components: {
+ Button: {
+ name: 'Button',
+ sdkBinding: {
+ sdk: 'nonexistent-sdk', // This doesn't exist
+ export: 'Button'
+ }
+ }
+ }
+ }
+ };
+
+ const tempPath = path.join(__dirname, 'temp-badref.json');
+ const fs = await import('fs');
+ fs.writeFileSync(tempPath, JSON.stringify(docWithBadRef));
+
+ try {
+ const result = await validator.validate(tempPath);
+ // Should have reference error
+ const refError = result.errors.find(e => e.type === 'reference');
+ assert.ok(refError, 'Should detect invalid SDK reference');
+ } finally {
+ fs.unlinkSync(tempPath);
+ }
+ });
+});
diff --git a/specs/fenestra/versions/core/0.1.0.md b/specs/fenestra/versions/core/0.1.0.md
new file mode 100644
index 0000000..165ea3b
--- /dev/null
+++ b/specs/fenestra/versions/core/0.1.0.md
@@ -0,0 +1,1040 @@
+# Fenestra Specification
+
+## Version 0.1.0
+
+The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP 14](https://tools.ietf.org/html/bcp14) [RFC2119](https://tools.ietf.org/html/rfc2119) [RFC8174](https://tools.ietf.org/html/rfc8174) when, and only when, they appear in all capitals, as shown here.
+
+This document is licensed under [The Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.html).
+
+## Abstract
+
+The Fenestra Specification defines a standard, programming language-agnostic mechanism to describe platform UI component ecosystems, SDK bindings, and UI rendering capabilities. The specification enables machine-readable documentation of how platforms expose UI extension points to developers building integrations, apps, and extensions.
+
+## Introduction
+
+Modern software platforms provide UI extension points with varying degrees of flexibility. Developers building integrations face a fragmented landscape where each platform has its own component libraries, SDK patterns, rendering engines, and publishing policies.
+
+**Fenestra** (Latin for "window") standardizes the description of:
+
+1. **Component Catalogs** - What UI components a platform provides
+2. **SDK Bindings** - How to import and use components from platform SDKs
+3. **Requirement Levels** - Whether platform components are required, recommended, or optional
+4. **Custom Component Policies** - Whether developers can bring their own components
+5. **Publishing Constraints** - Different rules for public vs private apps
+6. **Rendering Engines** - How UI definitions translate to rendered interfaces
+7. **Extension Points** - Where UI can be injected in the host platform
+
+A Fenestra Description can be used by:
+- **Documentation generators** to create consistent developer documentation
+- **Code generators** to scaffold integration projects with correct SDK imports
+- **Design tools** to render accurate previews of platform UI components
+- **AI assistants** to understand platform capabilities and generate valid UI code
+- **Validation tools** to verify that integration code follows platform policies
+
+### Relationship to Other Specifications
+
+The Fenestra Specification is designed to complement existing specifications:
+
+- **OpenAPI Specification**: Fenestra can reference OpenAPI descriptions for API endpoints that return or consume UI definitions. While OpenAPI describes API operations, Fenestra describes the UI layer.
+
+- **Arazzo Specification**: Workflow sequences defined in Arazzo can reference Fenestra UI definitions for steps that require user interaction.
+
+- **JSON Schema**: Fenestra uses JSON Schema for defining component properties, form schemas, and validation rules.
+
+- **MCP (Model Context Protocol)**: Fenestra's Agent UI extension type aligns with MCP Apps patterns for AI-driven UI.
+
+## Definitions
+
+### Fenestra Description
+
+A self-contained document (or set of documents) which describes a platform's UI component ecosystem. A Fenestra Description uses and conforms to the Fenestra Specification.
+
+### Platform
+
+The host application that provides UI extension capabilities. Examples include HubSpot, Salesforce, Slack, Figma, Stripe, and similar software platforms.
+
+### Extension Point
+
+A location within the host platform where third-party UI can be injected. Examples include sidebars, modals, cards, toolbar buttons, and canvas elements.
+
+### Extension Type
+
+The mechanism by which developers provide UI for an extension point. The five extension types are:
+- **JSON Response**: Developer returns JSON, platform renders
+- **Coded Components**: Developer writes code using platform SDK
+- **Iframe**: Developer provides web app loaded in iframe
+- **Embedded SDK**: Platform SDK embedded in developer's application
+- **Agent UI**: AI agent-driven UI with templates and custom fallback
+
+### Component Catalog
+
+The collection of UI components a platform provides to developers, including their properties, events, slots, and SDK bindings.
+
+### SDK Binding
+
+The mapping between a platform component and its import path in a software development kit (SDK).
+
+## Specification
+
+### Versions
+
+The Fenestra Specification is versioned using a `major.minor.patch` versioning scheme. The `major.minor` portion of the version string (for example `0.1`) SHALL designate the Fenestra feature set. Patch versions address errors in, or provide clarifications to, this document, not the feature set.
+
+Tooling which supports Fenestra 0.1 SHOULD be compatible with all Fenestra 0.1.\* versions. The patch version SHOULD NOT be considered by tooling.
+
+### Format
+
+A Fenestra Description that conforms to the Fenestra Specification is itself a JSON object, which may be represented either in JSON or YAML format.
+
+All field names in the specification are **case sensitive**. This includes all fields that are used as keys in a map.
+
+The schema exposes two types of fields: Fixed fields, which have a declared name, and Patterned fields, which declare a regex pattern for the field name.
+
+Patterned fields MUST have unique names within the containing object.
+
+In order to preserve the ability to round-trip between YAML and JSON formats, YAML version [1.2](https://yaml.org/spec/1.2/spec.html) is RECOMMENDED along with some additional constraints:
+
+- Tags MUST be limited to those allowed by the [JSON Schema ruleset](https://yaml.org/spec/1.2/spec.html#id2803231).
+- Keys used in YAML maps MUST be limited to a scalar string, as defined by the [YAML Failsafe schema ruleset](https://yaml.org/spec/1.2/spec.html#id2802346).
+
+### Data Types
+
+Data types in the Fenestra Specification are based on the types defined by [JSON Schema Specification Draft 2020-12](https://tools.ietf.org/html/draft-bhutton-json-schema-00#section-4.2.1).
+
+### Schema
+
+In the following description, if a field is not explicitly **REQUIRED** or described with a MUST or SHALL, it can be considered OPTIONAL.
+
+#### Fenestra Object
+
+This is the root object of a [Fenestra Description](#fenestraDescription).
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| fenestra | `string` | **REQUIRED**. This string MUST be the [version number](#versions) of the Fenestra Specification that the Fenestra Description uses. The `fenestra` field SHOULD be used by tooling to interpret the Fenestra Description. |
+| info | [Info Object](#infoObject) | **REQUIRED**. Provides metadata about the Fenestra Description. The metadata MAY be used by tooling as required. |
+| platform | [Platform Object](#platformObject) | Describes the host platform that provides the UI extension capabilities. |
+| sdks | Map[`string`, [SDK Object](#sdkObject)] | SDK ecosystem definitions indexed by SDK identifier. |
+| componentCatalog | [Component Catalog Object](#componentCatalogObject) | The catalog of UI components available on this platform. |
+| renderingEngines | Map[`string`, [Rendering Engine Object](#renderingEngineObject)] | Supported rendering engine configurations. |
+| policies | [Policies Object](#policiesObject) | Platform policies governing UI component usage, custom components, and publishing requirements. |
+| extensionPoints | [[Extension Point Object](#extensionPointObject)] | Where UI can be injected in the host platform. |
+
+This object MAY be extended with [Specification Extensions](#specificationExtensions).
+
+**Note:** Additional capabilities including declarative schemas, internationalization (i18n), compliance, and agent interaction are available as optional extensions to the Core specification.
+
+##### Fenestra Object Example
+
+```yaml
+fenestra: "0.1.0"
+info:
+ title: HubSpot UI Extensions
+ version: "1.0.0"
+ description: Fenestra description for HubSpot's UI Extensions platform
+platform:
+ name: HubSpot
+ vendor: HubSpot, Inc.
+ documentation: https://developers.hubspot.com/docs/platform/ui-extensions-overview
+sdks:
+ hubspot-ui-extensions:
+ name: HubSpot UI Extensions SDK
+ packageManager: npm
+ package: "@hubspot/ui-extensions"
+```
+
+#### Info Object
+
+The Info Object provides metadata about the Fenestra Description.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| title | `string` | **REQUIRED**. A human-readable title for the Fenestra Description. |
+| summary | `string` | A short summary of the platform's UI capabilities. |
+| description | `string` | A description of the platform's UI ecosystem. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. |
+| version | `string` | **REQUIRED**. The version of this Fenestra Description document (distinct from the Fenestra Specification version). |
+| termsOfService | `string` | A URI for the Terms of Service for the platform. This MUST be in the form of a URI. |
+| contact | [Contact Object](#contactObject) | The contact information for the exposed platform. |
+| license | [License Object](#licenseObject) | The license information for the Fenestra Description. |
+
+This object MAY be extended with [Specification Extensions](#specificationExtensions).
+
+##### Info Object Example
+
+```yaml
+info:
+ title: Canva Apps SDK
+ summary: Build apps that extend Canva's design platform
+ description: |
+ The Canva Apps SDK enables developers to create apps that integrate
+ with Canva's design editor, providing custom elements, asset sources,
+ and design tools.
+ version: "2.0.0"
+ termsOfService: https://www.canva.com/policies/developer-terms/
+ contact:
+ name: Canva Developer Relations
+ url: https://www.canva.dev
+ license:
+ name: Apache 2.0
+ url: https://www.apache.org/licenses/LICENSE-2.0
+```
+
+#### Contact Object
+
+Contact information for the platform.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| name | `string` | The identifying name of the contact person/organization. |
+| url | `string` | The URI pointing to the contact information. This MUST be in the form of a URI. |
+| email | `string` | The email address of the contact person/organization. This MUST be in the form of an email address. |
+
+This object MAY be extended with [Specification Extensions](#specificationExtensions).
+
+#### License Object
+
+License information for the Fenestra Description.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| name | `string` | **REQUIRED**. The license name used for the Fenestra Description. |
+| identifier | `string` | An [SPDX](https://spdx.org/spdx-specification-21-web-version#h.jxpfx0ykyb60) license expression for the Fenestra Description. |
+| url | `string` | A URI for the license used for the Fenestra Description. This MUST be in the form of a URI. |
+
+This object MAY be extended with [Specification Extensions](#specificationExtensions).
+
+#### Platform Object
+
+Describes the host platform that provides the UI extension capabilities.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| name | `string` | **REQUIRED**. The platform name. |
+| vendor | `string` | Platform vendor/company name. |
+| documentation | `string` | URI to platform developer documentation. This MUST be in the form of a URI. |
+| appMarketplace | `string` | URI to the platform's app marketplace/directory. This MUST be in the form of a URI. |
+
+This object MAY be extended with [Specification Extensions](#specificationExtensions).
+
+##### Platform Object Example
+
+```yaml
+platform:
+ name: Salesforce
+ vendor: Salesforce, Inc.
+ documentation: https://developer.salesforce.com
+ appMarketplace: https://appexchange.salesforce.com
+```
+
+#### SDK Object
+
+Describes an SDK package that provides UI components or utilities.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| name | `string` | **REQUIRED**. Human-readable SDK name. |
+| packageManager | `string` | **REQUIRED**. Package manager ecosystem. Values MUST be one of: `npm`, `yarn`, `pip`, `maven`, `gradle`, `nuget`, `cargo`, `go`, `composer`, `cocoapods`, `carthage`, `swift-package-manager`. |
+| package | `string` | **REQUIRED**. Package identifier (e.g., npm package name). |
+| version | `string` | Recommended or minimum version. |
+| platform | `string` | Target platform. Values MUST be one of: `web` (default), `ios`, `android`, `react-native`, `flutter`, `electron`. |
+| repository | `string` | Source code repository URI. |
+| documentation | `string` | SDK documentation URI. |
+| installCommand | `string` | Full install command for quick setup. |
+| cdn | `string` | CDN URI for script tag loading. |
+| cdnRequired | `boolean` | Whether SDK MUST be loaded from CDN (cannot be bundled). Default: `false`. |
+| typesPackage | `string` | TypeScript types package if separate from main package. |
+| starterTemplate | [Starter Template Object](#starterTemplateObject) | Starter template/scaffolding for new projects. |
+| cliTool | [CLI Tool Object](#cliToolObject) | Platform CLI tool for development. |
+| mobile | [Mobile SDK Object](#mobileSdkObject) | Mobile-specific SDK requirements (for iOS, Android, etc.). |
+| exports | Map[`string`, [SDK Export Object](#sdkExportObject)] | Named exports from the SDK package. |
+| subpackages | Map[`string`, [Subpackage Object](#subpackageObject)] | Additional subpackages within the SDK ecosystem. |
+
+This object MAY be extended with [Specification Extensions](#specificationExtensions).
+
+##### SDK Object Example
+
+```yaml
+sdks:
+ stripe-js:
+ name: Stripe.js
+ packageManager: npm
+ package: "@stripe/stripe-js"
+ version: "^2.0.0"
+ cdn: https://js.stripe.com/v3/
+ cdnRequired: true
+ installCommand: npm install @stripe/stripe-js
+ documentation: https://stripe.com/docs/js
+```
+
+#### Starter Template Object
+
+Starter template/scaffolding for new projects.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| command | `string` | CLI command to scaffold new project. |
+| repository | `string` | GitHub template repository URI. |
+| documentation | `string` | Documentation URI. |
+
+#### CLI Tool Object
+
+Platform CLI tool for development.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| package | `string` | CLI package name. |
+| installCommand | `string` | Command to install the CLI tool. |
+| commands | Map[`string`, `string`] | Key CLI commands and their usage. |
+
+#### SDK Export Object
+
+A named export from an SDK package.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| type | `string` | Type of export. Values MUST be one of: `component`, `hook`, `utility`, `icon`, `token`, `context`, `type`. |
+| description | `string` | What this export provides. |
+| deprecated | `boolean` | Whether this export is deprecated. Default: `false`. |
+| since | `string` | Version when this export was added. |
+
+#### Subpackage Object
+
+An additional subpackage within the SDK ecosystem.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| package | `string` | Package identifier. |
+| description | `string` | What this subpackage provides. |
+| exports | Map[`string`, [SDK Export Object](#sdkExportObject)] | Named exports from this subpackage. |
+
+#### Mobile SDK Object
+
+Mobile-specific SDK requirements for iOS, Android, and cross-platform frameworks.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| minOsVersion | `string` | Minimum OS version required (e.g., "13.0" for iOS). |
+| targetOsVersion | `string` | Recommended target OS version. |
+| capabilities | [`string`] | Required device capabilities (e.g., `camera`, `biometrics`, `nfc`). |
+| permissions | Map[`string`, `string`] | Required permissions with usage descriptions. Keys are platform-specific (e.g., `NSCameraUsageDescription` for iOS). |
+| architectures | [`string`] | Supported CPU architectures (e.g., `arm64`, `x86_64`). |
+| frameworks | [`string`] | Required or supported UI frameworks (e.g., `UIKit`, `SwiftUI`, `Jetpack Compose`). |
+| appStoreGuidelines | `string` | URI to relevant app store review guidelines. |
+
+##### Mobile SDK Object Example
+
+```yaml
+sdks:
+ docusign-ios:
+ name: DocuSign iOS SDK
+ packageManager: cocoapods
+ package: DocuSign
+ platform: ios
+ mobile:
+ minOsVersion: "13.0"
+ targetOsVersion: "17.0"
+ capabilities:
+ - camera
+ - biometrics
+ permissions:
+ NSCameraUsageDescription: "Capture documents for signing"
+ NSFaceIDUsageDescription: "Authenticate with Face ID"
+ architectures:
+ - arm64
+ frameworks:
+ - UIKit
+ - SwiftUI
+```
+
+#### Component Catalog Object
+
+The catalog of UI components available on this platform.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| categories | Map[`string`, [Component Category Object](#componentCategoryObject)] | Component categories (layout, input, display, etc.). |
+| components | Map[`string`, [Component Object](#componentObject)] | All components indexed by canonical identifier. |
+
+This object MAY be extended with [Specification Extensions](#specificationExtensions).
+
+#### Component Category Object
+
+A category of related components.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| name | `string` | Category display name. |
+| description | `string` | Category description. |
+| components | [`string`] | References to component identifiers in this category. |
+
+#### Component Object
+
+A UI component provided by the platform.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| name | `string` | **REQUIRED**. Component display name. |
+| description | `string` | What this component does. |
+| category | `string` | Category this component belongs to. |
+| sdkBinding | [SDK Binding Object](#sdkBindingObject) | How to import this component from an SDK. |
+| webStandardMapping | [Web Standard Mapping Object](#webStandardMappingObject) | Maps this component to web platform standards. |
+| props | `object` | Component properties/attributes (JSON Schema format). |
+| slots | Map[`string`, [Slot Object](#slotObject)] | Named slots/children this component accepts. |
+| events | Map[`string`, [Component Event Object](#componentEventObject)] | Events this component can emit. |
+| variants | [`string`] | Visual or behavioral variants. |
+| accessibility | [Accessibility Object](#accessibilityObject) | Accessibility information. |
+| examples | [[Component Example Object](#componentExampleObject)] | Usage examples. |
+
+This object MAY be extended with [Specification Extensions](#specificationExtensions).
+
+##### Component Object Example
+
+```yaml
+components:
+ Button:
+ name: Button
+ description: A clickable button for triggering actions
+ category: input
+ sdkBinding:
+ sdk: hubspot-ui-extensions
+ export: Button
+ webStandardMapping:
+ htmlElement: button
+ ariaRole: button
+ semanticType: action
+ props:
+ type: object
+ properties:
+ variant:
+ type: string
+ enum: [primary, secondary, destructive]
+ disabled:
+ type: boolean
+ onClick:
+ type: function
+ events:
+ click:
+ description: Fired when button is clicked
+```
+
+#### SDK Binding Object
+
+How to import a component from an SDK.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| sdk | `string` | **REQUIRED**. Reference to SDK identifier in the `sdks` object. |
+| subpackage | `string` | Subpackage within the SDK (if applicable). |
+| export | `string` | **REQUIRED**. Named export from the package. |
+| importPath | `string` | Full import path if different from default package. |
+
+#### Web Standard Mapping Object
+
+Maps a platform component to web platform standards.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| htmlElement | `string` | Closest HTML element equivalent. |
+| ariaRole | `string` | ARIA role this component fulfills. |
+| webComponent | `string` | Web Components standard equivalent (if any). |
+| semanticType | `string` | Semantic UI pattern type. Values MUST be one of: `action`, `input`, `display`, `layout`, `navigation`, `feedback`, `container`. |
+
+#### Slot Object
+
+A named slot/children a component accepts.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| description | `string` | What content this slot accepts. |
+| required | `boolean` | Whether this slot is required. Default: `false`. |
+| accepts | [`string`] | Component types this slot accepts. |
+
+#### Component Event Object
+
+An event a component can emit.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| description | `string` | What triggers this event. |
+| payload | `object` | JSON Schema for event payload. |
+
+#### Accessibility Object
+
+Accessibility information for a component.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| keyboardSupport | `boolean` | Whether the component supports keyboard navigation. |
+| screenReaderSupport | `boolean` | Whether the component supports screen readers. |
+| focusManagement | `string` | How focus is managed. |
+| notes | `string` | Additional accessibility notes. |
+
+#### Component Example Object
+
+A usage example for a component.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| title | `string` | Example title. |
+| description | `string` | Example description. |
+| code | `string` | Example code snippet. |
+| language | `string` | Code language. Default: `jsx`. |
+
+#### Rendering Engine Object
+
+A rendering engine that interprets UI definitions.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| type | `string` | **REQUIRED**. Rendering paradigm. Values MUST be one of: `jsonForms`, `jsonSchema`, `mcpApps`, `react`, `webComponents`, `lwc`, `custom`. |
+| name | `string` | Human-readable engine name. |
+| description | `string` | Engine description. |
+| schemaSupport | [Schema Support Object](#schemaSupportObject) | Schema-based rendering configuration. |
+| sandboxing | [Sandbox Config Object](#sandboxConfigObject) | Security sandboxing configuration. |
+
+This object MAY be extended with [Specification Extensions](#specificationExtensions).
+
+#### Schema Support Object
+
+Schema-based rendering configuration.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| dataSchema | `string` | Schema format for data definition. Values MUST be one of: `jsonSchema`, `custom`. |
+| uiSchema | `string` | Schema format for UI definition. Values MUST be one of: `jsonFormsUISchema`, `mcpAppsTemplate`, `custom`. |
+| customRenderers | `boolean` | Whether custom renderers can be registered. Default: `false`. |
+
+#### Sandbox Config Object
+
+Security sandboxing configuration for rendered UI.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| iframeSandbox | `boolean` | Whether UI runs in sandboxed iframe. |
+| sandboxAttributes | [`string`] | iframe sandbox attribute values. |
+| cspPolicy | `string` | Content Security Policy for rendered content. |
+
+#### Policies Object
+
+Platform policies governing UI component usage.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| componentRequirement | [Component Requirement Policy Object](#componentRequirementPolicyObject) | Whether platform-provided components are required. |
+| customComponents | [Custom Component Policy Object](#customComponentPolicyObject) | Whether developers can bring their own components. |
+| publishing | [Publishing Policy Object](#publishingPolicyObject) | Different rules for public vs private apps. |
+| designGuidelines | [Design Guidelines Policy Object](#designGuidelinesPolicyObject) | Platform design system and guidelines. |
+
+This object MAY be extended with [Specification Extensions](#specificationExtensions).
+
+#### Component Requirement Policy Object
+
+Whether platform-provided components are required.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| level | `string` | Requirement level. Values MUST be one of: `required` (must use platform components exclusively), `recommended` (platform components preferred, alternatives allowed), `optional` (platform components available but not required). |
+| scope | `string` | What app types this requirement applies to. Values MUST be one of: `all`, `publicApps`, `marketplaceApps`. |
+| rationale | `string` | Why this policy exists. |
+| exceptions | [`string`] | Documented exceptions to this policy. |
+
+#### Custom Component Policy Object
+
+Whether developers can bring their own (BYO) components.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| allowed | `boolean` | Whether custom components are permitted at all. |
+| constraints | [`string`] | Constraints on custom components. Values MUST be from: `mustWrapPlatformPrimitives`, `mustFollowDesignSystem`, `mustPassAccessibilityAudit`, `requiresReview`, `sandboxOnly`. |
+| registrationRequired | `boolean` | Whether custom components must be registered. Default: `false`. |
+| approvalRequired | `boolean` | Whether custom components require platform approval. Default: `false`. |
+| documentation | `string` | Documentation URI for custom component requirements. |
+
+#### Publishing Policy Object
+
+Different rules for public/marketplace apps vs private/internal apps.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| privateApps | [App Policy Object](#appPolicyObject) | Rules for private/internal apps. |
+| publicApps | [App Policy Object](#appPolicyObject) | Rules for public apps. |
+| marketplaceApps | [App Policy Object](#appPolicyObject) | Rules for apps published to official marketplace. |
+
+#### App Policy Object
+
+Policy rules for a specific app type.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| componentRequirement | `string` | Requirement level. Values: `required`, `recommended`, `optional`. |
+| customComponentsAllowed | `boolean` | Whether custom components are allowed. |
+| reviewRequired | `boolean` | Whether review is required. |
+| designReviewRequired | `boolean` | Whether design review is required. |
+| accessibilityAuditRequired | `boolean` | Whether accessibility audit is required. |
+| certificationRequired | `boolean` | Whether certification is required. |
+| notes | `string` | Additional notes. |
+
+#### Design Guidelines Policy Object
+
+Platform design system and guidelines.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| required | `boolean` | Whether following guidelines is mandatory. |
+| designSystem | `string` | Name of the design system. |
+| designSystemUrl | `string` | URI to design system documentation. |
+| designTokensProvided | `boolean` | Whether design tokens are available for custom styling. |
+
+#### Extension Point Object
+
+A location in the host platform where UI can be injected.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| id | `string` | **REQUIRED**. Unique identifier for this extension point. |
+| name | `string` | **REQUIRED**. Human-readable name. |
+| type | `string` | **REQUIRED**. Type of extension point. Values MUST be one of: `sidebar`, `modal`, `panel`, `card`, `toolbar`, `contextMenu`, `canvas`, `composer`, `fullPage`, `embedded`. |
+| extensionType | `string` | **REQUIRED**. How the developer provides UI. Values MUST be one of: `jsonResponse`, `codedComponents`, `iframe`, `embeddedSdk`. |
+| extensionTypeConfig | [JSON Response Config Object](#jsonResponseConfigObject) \| [Coded Components Config Object](#codedComponentsConfigObject) \| [Iframe Config Object](#iframeConfigObject) \| [Embedded SDK Config Object](#embeddedSdkConfigObject) | Configuration specific to the extension type. |
+| description | `string` | Extension point description. |
+| supportedComponents | [`string`] | Component types allowed at this extension point. |
+| constraints | [Constraints Object](#constraintsObject) | Size and behavior constraints. |
+| context | [Context Object](#contextObject) | Data context available at this extension point. |
+
+This object MAY be extended with [Specification Extensions](#specificationExtensions).
+
+##### Extension Point Object Example
+
+```yaml
+extensionPoints:
+ - id: crm-record-sidebar
+ name: CRM Record Sidebar
+ type: sidebar
+ extensionType: codedComponents
+ description: Sidebar panel on CRM record pages
+ supportedComponents:
+ - Card
+ - Button
+ - Table
+ - Form
+ context:
+ provides:
+ - currentRecord
+ - user
+```
+
+#### Constraints Object
+
+Size and behavior constraints for an extension point.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| maxWidth | `integer` | Maximum width in pixels. |
+| maxHeight | `integer` | Maximum height in pixels. |
+| responsive | `boolean` | Whether extension must be responsive. |
+
+#### Context Object
+
+Data context available at an extension point.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| provides | [`string`] | Context data types provided. |
+| actions | [`string`] | Actions that can be performed from this context. |
+
+#### JSON Response Config Object
+
+Configuration for JSON Response extension type. Developer returns JSON from endpoint, platform renders pre-built components.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| schema | [Response Schema Object](#responseSchemaObject) | JSON Schema definition for valid responses. |
+| endpoint | [Endpoint Object](#endpointObject) | How the platform calls the developer's endpoint. |
+| interactivity | [Interactivity Object](#interactivityObject) | How user interactions are handled. |
+
+#### Response Schema Object
+
+JSON Schema definition for valid responses.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| format | `string` | Schema format identifier (e.g., `slack.blocks`, `adaptive-cards`). |
+| version | `string` | Schema version. |
+| schemaUrl | `string` | URI to full JSON Schema definition. |
+| encoding | `string` | Character encoding. Default: `UTF-8`. |
+
+#### Endpoint Object
+
+How the platform calls the developer's endpoint.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| method | `string` | HTTP method. Values: `GET`, `POST`. Default: `POST`. |
+| contentType | `string` | Content type. Default: `application/json`. |
+| timeout | `integer` | Request timeout in seconds. Default: `10`. |
+| authentication | `string` | How requests are authenticated. Values: `none`, `oauth`, `jwt`, `signedRequest`, `apiKey`. |
+| contextProvided | [`string`] | Context data sent with each request. |
+
+#### Interactivity Object
+
+How user interactions are handled.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| callbackUrl | `boolean` | Whether platform POSTs interactions to callback URL. |
+| payloadTypes | [`string`] | Types of interaction payloads. |
+
+#### Coded Components Config Object
+
+Configuration for Coded Components extension type. Developer writes code using platform's SDK/UI Kit.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| sdk | `string` | Reference to SDK in the `sdks` object. |
+| framework | `string` | Required or primary framework. Values: `react`, `vue`, `lwc`, `webComponents`, `agnostic`. |
+| runtime | [Runtime Object](#runtimeObject) | How developer code is executed. |
+| hostInteraction | [JS SDK Config Object](#jsSdkConfigObject) | Host interaction SDK configuration. |
+
+#### Runtime Object
+
+How developer code is executed.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| type | `string` | Execution environment. Values: `sandboxedIframe`, `webWorker`, `directExecution`. |
+| bundling | `string` | How code is bundled and deployed. Values: `platformBuild`, `developerBuild`, `cdn`. |
+
+#### Iframe Config Object
+
+Configuration for Iframe extension type. Developer provides full web app at URL, platform loads in iframe.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| sandboxAttributes | [`string`] | iframe sandbox attribute values. |
+| cspRequirements | `string` | Required Content Security Policy. |
+| sizeConstraints | [Size Constraints Object](#sizeConstraintsObject) | Size constraints for the iframe. |
+| communication | [JS SDK Config Object](#jsSdkConfigObject) | Communication SDK configuration. |
+
+#### Size Constraints Object
+
+Size constraints for iframes or UI elements.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| minWidth | `integer` | Minimum width in pixels. |
+| maxWidth | `integer` | Maximum width in pixels. |
+| minHeight | `integer` | Minimum height in pixels. |
+| maxHeight | `integer` | Maximum height in pixels. |
+| resizable | `boolean` | Whether element can be resized dynamically. |
+
+#### Embedded SDK Config Object
+
+Configuration for Embedded SDK extension type. Platform SDK is embedded in developer's own application.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| sdk | [Embedded SDK Details Object](#embeddedSdkDetailsObject) | SDK package details. |
+| mountPattern | `string` | How SDK components are mounted. Values: `domSelector`, `reactComponent`, `webComponent`, `function`. |
+| theming | [Theming Object](#themingObject) | Styling/theming capabilities. |
+| communication | [Communication Object](#communicationObject) | Communication pattern configuration. |
+
+#### Embedded SDK Details Object
+
+SDK package details for embedded SDK.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| package | `string` | npm/CDN package name. |
+| cdn | `string` | CDN URI (often required for security). |
+| cdnRequired | `boolean` | Whether SDK MUST be loaded from CDN. Default: `false`. |
+
+#### Theming Object
+
+Styling/theming capabilities.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| system | `string` | Theming system name. |
+| prebuiltThemes | [`string`] | Available pre-built themes. |
+| customizable | `boolean` | Whether theming is customizable. |
+| variables | [`string`] | Customizable theme variables. |
+
+#### Communication Object
+
+Communication pattern configuration.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| pattern | `string` | Primary async communication pattern. Values: `callbacks`, `events`, `promises`, `observables`. |
+| events | [`string`] | Events the SDK can emit. |
+
+#### JS SDK Config Object
+
+Configuration for JavaScript SDK that enables host interaction.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| globalObject | `string` | Global window object name (e.g., `miro`, `Front`, `ZAFClient`). |
+| package | `string` | npm package name (if applicable). |
+| cdn | `string` | CDN script URI. |
+| initialization | [Initialization Object](#initializationObject) | How SDK is initialized. |
+| namespaces | Map[`string`, [Namespace Object](#namespaceObject)] | SDK namespace structure. |
+| capabilities | [SDK Capabilities Object](#sdkCapabilitiesObject) | What the SDK can do. |
+| asyncPattern | `string` | Primary async pattern used. Values: `promises`, `callbacks`, `observables`, `sync`. |
+
+#### Initialization Object
+
+How an SDK is initialized.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| method | `string` | How SDK is initialized (e.g., `auto`, `ZAFClient.init()`). |
+| async | `boolean` | Whether initialization is async. |
+
+#### Namespace Object
+
+An SDK namespace.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| description | `string` | What this namespace provides. |
+| methods | [`string`] | Methods available in this namespace. |
+
+#### SDK Capabilities Object
+
+What an SDK can do.
+
+##### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| context | `boolean` | Can access current context/state. |
+| uiActions | `boolean` | Can trigger platform UI (toasts, modals). |
+| dataActions | `boolean` | Can perform CRUD on platform data. |
+| events | `boolean` | Can subscribe to platform events. |
+
+### Specification Extensions
+
+While the Fenestra Specification tries to accommodate most use cases, additional data can be added to extend the specification at certain points.
+
+The extensions properties are implemented as patterned fields that are always prefixed by `x-`.
+
+| Field Pattern | Type | Description |
+|---|---|---|
+| ^x- | Any | Allows extensions to the Fenestra Schema. The field name MUST begin with `x-`, for example, `x-internal-id`. Field names beginning with `x-oai-` and `x-oas-` are reserved for uses defined by the [OpenAPI Initiative](https://www.openapis.org/). The value can be any valid JSON value (`null`, a primitive, an array, or an object). |
+
+The extensions may or may not be supported by the available tooling, but those may be extended as well to add requested support (if tools are internal or open-source).
+
+### Security Considerations
+
+This section provides security guidance for Fenestra Description authors, platform implementers, tooling developers, and consumers. The Fenestra Specification is a **description format**, not an enforcement mechanism—it cannot make platforms secure, but it provides vocabulary to describe security posture and recommends validation practices.
+
+#### Trust Model
+
+A Fenestra Description is an assertion by a platform about its capabilities, requirements, and compliance posture. Consumers of Fenestra Descriptions SHOULD understand:
+
+1. **Fenestra Descriptions are not self-certifying.** A document claiming `compliance.security.platformCertifications: ["SOC2 Type II"]` does not prove SOC2 compliance. Consumers requiring compliance verification SHOULD request audit reports through appropriate channels.
+
+2. **No built-in document signing.** The specification does not currently define a signing mechanism. Platforms publishing official Fenestra Descriptions SHOULD host them at well-known URLs under their control and MAY implement signing using external mechanisms (e.g., JWS, GPG signatures).
+
+3. **Tooling should validate, not trust.** Tools processing Fenestra Descriptions SHOULD validate claims where possible (e.g., verifying that SDK packages exist, checking that URIs resolve) rather than trusting all assertions.
+
+#### Document Authoring
+
+Authors of Fenestra Descriptions SHOULD:
+
+- **Never include secrets.** API keys, credentials, tokens, and signing keys MUST NOT appear in Fenestra Descriptions.
+- **Use HTTPS URIs.** All `schemaUrl`, `documentation`, `cdn`, and similar URI fields SHOULD use HTTPS.
+- **Provide accurate compliance information.** Misrepresenting security certifications or compliance status may have legal consequences.
+- **Version documents appropriately.** Security-relevant changes SHOULD result in version updates.
+- **Consider access control.** Internal Fenestra Descriptions describing private APIs or unpublished features SHOULD be access-controlled.
+
+#### URI and Schema Handling
+
+Fenestra Descriptions contain URIs that tooling may fetch (e.g., `schemaUrl`, `cdn`, `documentation`). Tooling SHOULD:
+
+- **Validate URI schemes.** Only `https:` URIs SHOULD be fetched automatically. `http:`, `file:`, `data:`, and `javascript:` URIs SHOULD be rejected or require explicit user approval.
+- **Prevent SSRF attacks.** Tooling MUST NOT fetch URIs pointing to internal networks, localhost, or cloud metadata endpoints (e.g., `169.254.169.254`).
+- **Limit redirect following.** Tooling SHOULD limit redirects and SHOULD NOT follow redirects to different origins without user awareness.
+- **Validate JSON Schema references.** `$ref` URIs in embedded JSON Schemas SHOULD be validated before fetching. Remote `$ref` resolution SHOULD be disabled by default or sandboxed.
+- **Apply timeouts.** URI fetches SHOULD have reasonable timeouts to prevent resource exhaustion.
+
+#### Content Security Policy and Sandboxing
+
+The specification includes CSP and sandbox configuration fields. These fields describe platform requirements but do not enforce them.
+
+**For Platform Authors:**
+- CSP policies in `cspRequirements` and `sandboxConfig.cspPolicy` SHOULD follow the principle of least privilege.
+- Avoid overly permissive policies like `default-src *` or `script-src 'unsafe-inline' 'unsafe-eval'`.
+- Document the security rationale for required sandbox attributes.
+
+**For Tooling:**
+- Tooling rendering Fenestra documentation SHOULD apply its own CSP, not trust CSP values from the document.
+- Tooling that previews or executes extension code SHOULD apply strict sandboxing regardless of document claims.
+
+**For Extension Developers:**
+- Treat `iframeConfig.sandboxAttributes` and `cspRequirements` as minimum requirements, not security guarantees.
+- Implement defense-in-depth; do not rely solely on platform-provided sandboxing.
+
+#### Agent Interaction Security
+
+The `agentInteraction` section describes AI agent capabilities. This area requires particular security attention:
+
+**Permission Scoping:**
+- The `agentPermissions` object uses boolean flags (e.g., `canPerformActions`). Platform implementations SHOULD interpret these as capability advertisements, not authorization grants.
+- Actual agent authorization SHOULD be handled through platform authentication systems, not Fenestra Descriptions.
+- Platforms SHOULD implement fine-grained permissions at runtime, even if the Fenestra Description uses coarse-grained capability flags.
+
+**Prompt Injection Risks:**
+- Template `description` fields and other text content MAY be processed by AI agents. Platform implementers SHOULD sanitize or escape content that will be included in AI prompts.
+- Tooling SHOULD NOT automatically execute agent templates discovered in untrusted Fenestra Descriptions.
+
+**Context Data:**
+- The `agentContext.available` field describes what data agents can access. Platforms MUST implement appropriate access controls at runtime.
+- PII filtering (`agentContext.piiFiltering`) is a capability advertisement. Actual filtering MUST be implemented by the platform, not assumed from the document.
+
+**Protocol Security:**
+- When `agentInteraction.protocols` lists multiple protocols, platforms SHOULD prefer secure protocols and SHOULD NOT allow downgrade attacks.
+- Custom protocols (`name: "custom"`) SHOULD be documented with their security properties.
+
+#### SDK and CDN Security
+
+**Subresource Integrity:**
+- When SDKs are loaded from CDN (`sdk.cdn`), extension developers SHOULD use Subresource Integrity (SRI) hashes.
+- Platforms MAY document recommended integrity hashes in `x-` extension fields.
+- When `cdnRequired: true`, the platform is requiring loading from an external source—extension developers SHOULD verify the CDN's trustworthiness.
+
+**Package Verification:**
+- SDK packages (`sdk.package`) reference external package registries. Tooling SHOULD verify package existence but SHOULD NOT automatically install packages from untrusted Fenestra Descriptions.
+- Platforms SHOULD publish SDKs from verified accounts on package registries.
+
+#### Compliance Documentation
+
+The `compliance` section provides vocabulary for describing security, privacy, and accessibility posture. This information is **descriptive, not normative**:
+
+- **Certifications** listed in `platformCertifications` are claims, not proofs. Verification requires obtaining actual audit reports.
+- **Shared responsibility** boundaries in `sharedResponsibility` are informational. Legal responsibility is determined by contracts, not Fenestra Descriptions.
+- **Privacy compliance** flags (e.g., `gdpr: true`) indicate the platform's self-assessment. GDPR compliance requires ongoing operational practices, not just a boolean flag.
+
+**Recommendations for Compliance-Sensitive Environments:**
+1. Use Fenestra Descriptions as a starting point for vendor assessment, not as sufficient evidence.
+2. Request supporting documentation (SOC2 reports, DPAs, VPATs) through appropriate channels.
+3. Conduct independent security assessments for high-risk integrations.
+
+#### Tooling Implementation
+
+Tools processing Fenestra Descriptions SHOULD implement the following security practices:
+
+| Concern | Recommendation |
+|---------|----------------|
+| URI fetching | Allowlist schemes, block internal IPs, limit redirects, apply timeouts |
+| JSON Schema | Disable or sandbox remote `$ref` resolution |
+| Package installation | Never auto-install; require explicit user approval |
+| Code generation | Sanitize identifiers to prevent injection in generated code |
+| Documentation rendering | Apply CSP, sanitize HTML/Markdown, escape user-controlled content |
+| Agent template execution | Require explicit user approval, sandbox execution |
+| Validation | Warn on suspicious patterns (permissive CSP, missing HTTPS, etc.) |
+
+#### Reporting Security Issues
+
+Security vulnerabilities in the Fenestra Specification itself should be reported to the specification maintainers through responsible disclosure practices. Vulnerabilities in specific platform implementations should be reported to those platforms directly.
+
+## Appendix A: Revision History
+
+| Version | Date | Notes |
+|---------|------|-------|
+| 0.1.0 | 2024-12-27 | Initial draft |
diff --git a/specs/fenestra/versions/extensions/agents/0.1.0.md b/specs/fenestra/versions/extensions/agents/0.1.0.md
new file mode 100644
index 0000000..a376c28
--- /dev/null
+++ b/specs/fenestra/versions/extensions/agents/0.1.0.md
@@ -0,0 +1,652 @@
+# Fenestra Agents Extension
+
+## Version 0.1.0
+
+The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP 14](https://tools.ietf.org/html/bcp14) [RFC2119](https://tools.ietf.org/html/rfc2119) [RFC8174](https://tools.ietf.org/html/rfc8174) when, and only when, they appear in all capitals, as shown here.
+
+This document is licensed under [The Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.html).
+
+## Abstract
+
+The Fenestra Agents Extension provides vocabulary for describing AI agent interaction mechanisms within platform UI ecosystems. This extension enables machine-readable documentation of agent protocols (MCP, OpenAI functions, Anthropic tools), UI invocation patterns, discovery mechanisms, permissions, event handling, and context sharing. It supports both template-based UI generation and custom iframe fallback patterns, aligning with the Model Context Protocol (MCP) Apps specification while remaining protocol-agnostic.
+
+## Introduction
+
+Modern platforms are increasingly integrating AI agents as first-class citizens in their extension ecosystems. Agents need to understand available UI capabilities, invoke templates, open custom interfaces, receive user interaction events, and operate within appropriate permission boundaries.
+
+The Fenestra Agents Extension standardizes the description of:
+
+1. **Agent Protocols** - Supported communication protocols (MCP, OpenAI functions, Anthropic tools, LangChain tools)
+2. **UI Invocation** - How agents invoke UI templates and custom interfaces
+3. **Discovery** - How agents discover available templates, actions, and capabilities
+4. **Context Passing** - What contextual information is available to agents
+5. **Event Handling** - How user interactions are communicated back to agents
+6. **Permissions** - Authorization boundaries for agent actions
+7. **Templates** - Pre-declared UI templates agents can invoke
+8. **Custom UI** - Iframe-based fallback for complex UI needs
+
+This extension aligns with the **Model Context Protocol (MCP)** Apps pattern where agents can invoke pre-declared UI templates or open custom UI, but remains protocol-agnostic to support multiple agent frameworks.
+
+## Relationship to Fenestra Core
+
+This extension adds an optional `agentInteraction` field to the Fenestra Object at the root level. It describes agent-side interaction patterns and capabilities.
+
+The Agents Extension complements (but is distinct from) the `agentUI` extension type defined in Fenestra Core:
+
+- **Core `agentUI` Extension Type**: Describes how platforms render agent-driven UI (templates, custom iframe config, communication patterns). This is an extension point configuration.
+- **Agents Extension (`agentInteraction`)**: Describes how agents interact with the platform (protocols, discovery, permissions, events). This is a platform-level capability declaration.
+
+A complete agent integration description typically includes both:
+```yaml
+fenestra: "0.1.0"
+extensionPoints:
+ - id: agent-sidebar
+ extensionType: agentUI
+ extensionTypeConfig:
+ templates:
+ supported: [form, approval, display]
+ customUI:
+ allowed: true
+ # ... (platform rendering config)
+
+agentInteraction:
+ protocols:
+ - name: mcp
+ version: "1.0"
+ discovery:
+ templateDiscovery: true
+ permissions:
+ canInvokeTemplates: true
+ # ... (agent capabilities)
+```
+
+## Security Considerations
+
+AI agent interactions introduce specific security considerations that platform implementers, tooling developers, and extension authors must address.
+
+### Agent Permission Model
+
+The `agentPermissions` object uses boolean capability flags (e.g., `canPerformActions`, `canAccessUserData`). Platform implementations SHOULD interpret these as capability advertisements, not authorization grants.
+
+**Recommendations:**
+
+1. **Runtime Authorization**: Actual agent authorization MUST be handled through platform authentication systems, not Fenestra Descriptions.
+2. **Fine-Grained Permissions**: Platforms SHOULD implement fine-grained permissions at runtime, even if the Fenestra Description uses coarse-grained capability flags.
+3. **Least Privilege**: Agents SHOULD be granted the minimum permissions necessary for their function.
+4. **User Approval**: When `userApprovalRequired.forActions` or `userApprovalRequired.forDataAccess` is true, platforms MUST obtain explicit user consent before allowing agent actions.
+
+### Prompt Injection Risks
+
+Template `description` fields, `name` values, and other text content MAY be processed by AI agents for capability discovery.
+
+**Risks:**
+- Malicious template descriptions could contain prompt injection attacks designed to manipulate agent behavior.
+- Discovery manifests could be crafted to mislead agents about available capabilities.
+
+**Mitigations:**
+1. **Sanitization**: Platform implementers SHOULD sanitize or escape content included in AI prompts.
+2. **Validation**: Tooling SHOULD validate template schemas and reject suspicious patterns.
+3. **No Auto-Execution**: Tooling MUST NOT automatically execute agent templates discovered in untrusted Fenestra Descriptions.
+4. **User Confirmation**: High-privilege actions SHOULD require user confirmation even if agents request them.
+
+### Context Data Security
+
+The `agentContext` object describes what contextual information agents can access (e.g., `conversationHistory`, `userIdentity`, `currentDocument`).
+
+**Requirements:**
+
+1. **Access Control**: Platforms MUST implement appropriate access controls at runtime. The Fenestra Description advertises capabilities but does not grant access.
+2. **PII Filtering**: When `agentContext.piiFiltering` is set to `automatic` or `manual`, platforms MUST implement actual filtering mechanisms. This field describes capability, not configuration.
+3. **Data Minimization**: Only provide agents with context data necessary for the current task.
+4. **User Awareness**: Users SHOULD be informed what context data is shared with agents.
+
+**Example Risk**: If `available: ["conversationHistory"]` is declared, an agent could potentially access sensitive information from previous conversations. Platforms MUST implement appropriate retention limits, access logging, and user controls.
+
+### Protocol Security
+
+When `agentInteraction.protocols` lists multiple protocols, security considerations include:
+
+1. **Protocol Preference**: Platforms SHOULD prefer more secure protocols when multiple options are available.
+2. **No Downgrade Attacks**: Platforms MUST NOT allow agents to force downgrades to less secure protocols.
+3. **Custom Protocol Documentation**: When `name: "custom"` is used, the `documentation` field SHOULD link to detailed security properties of the protocol.
+4. **Version Pinning**: Protocol versions SHOULD be explicitly specified to prevent unexpected behavior from version mismatches.
+
+### Discovery Manifest Security
+
+When `agentDiscovery.manifest` points to a URI, tooling fetching this manifest SHOULD:
+
+1. **HTTPS Only**: Reject `http://` URIs unless in development environments.
+2. **SSRF Prevention**: Block requests to internal networks, localhost, or cloud metadata endpoints.
+3. **Validation**: Validate manifest schema before processing.
+4. **Caching**: Cache manifests appropriately but respect cache headers to allow security updates.
+
+### Template Input/Output Validation
+
+Agent templates define `inputSchema` and `outputSchema` as JSON Schema objects. Platforms SHOULD:
+
+1. **Schema Validation**: Validate all agent-provided inputs against `inputSchema` before rendering templates.
+2. **Output Validation**: Validate user responses against `outputSchema` before returning to agents.
+3. **Injection Prevention**: Sanitize template inputs to prevent XSS or other injection attacks in rendered UI.
+4. **Size Limits**: Enforce reasonable size limits on template inputs to prevent resource exhaustion.
+
+### Event Delivery Security
+
+When `agentEvents.delivery` is set to `webhook`, additional security measures are required:
+
+1. **Authentication**: Webhook endpoints MUST be authenticated (signature verification, API keys).
+2. **HTTPS Only**: Webhook URLs MUST use HTTPS.
+3. **Replay Protection**: Implement timestamp validation and nonce tracking to prevent replay attacks.
+4. **Rate Limiting**: Apply rate limits to prevent webhook flooding.
+
+### Custom UI Sandboxing
+
+When agents can open custom UI (`agentPermissions.canOpenCustomUI: true`), strict sandboxing is essential:
+
+1. **Sandbox Attributes**: Custom UI iframes MUST apply restrictive sandbox attributes (see `customUI.sandboxAttributes`).
+2. **CSP Enforcement**: Apply Content Security Policy to prevent unauthorized resource loading.
+3. **Origin Isolation**: Custom UI SHOULD be served from a separate origin to prevent access to platform cookies/storage.
+4. **User Confirmation**: Opening custom UI MAY require user confirmation, especially for untrusted agents.
+
+### Audit and Monitoring
+
+Platforms implementing agent interactions SHOULD:
+
+1. **Action Logging**: Log all agent-invoked UI actions, template invocations, and custom UI openings.
+2. **Anomaly Detection**: Monitor for unusual patterns (excessive UI invocations, suspicious template parameters).
+3. **User Access**: Provide users with visibility into what agents have done on their behalf.
+4. **Revocation**: Allow users to revoke agent permissions or terminate agent sessions.
+
+## Schema
+
+### Agent Interaction Object
+
+AI agent interaction mechanisms and protocols. This object is added at the root level of a Fenestra Description.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| capabilities | [Agent Capabilities Summary Object](#agentCapabilitiesSummaryObject) | High-level agent interaction capabilities. |
+| protocols | [[Agent Protocol Object](#agentProtocolObject)] | Supported agent protocols. |
+| discovery | [Agent Discovery Object](#agentDiscoveryObject) | How agents discover UI capabilities. |
+| context | [Agent Context Object](#agentContextObject) | Context passing to agents. |
+| uiInvocation | [UI Invocation Object](#uiInvocationObject) | How agents invoke UI. |
+| events | [Agent Events Object](#agentEventsObject) | Events sent back to agents. |
+| permissions | [Agent Permissions Object](#agentPermissionsObject) | Agent permission model. |
+
+This object MAY be extended with [Specification Extensions](#specificationExtensions).
+
+#### Agent Interaction Object Example
+
+```yaml
+agentInteraction:
+ capabilities:
+ templateInvocation: true
+ customUISupport: true
+ eventCallbacks: true
+ actionChaining: true
+ protocols:
+ - name: mcp
+ version: "1.0"
+ package: "@docusign/mcp-server"
+ documentation: https://developers.docusign.com/mcp
+ - name: openai-functions
+ schemaFormat: openapi
+ discovery:
+ templateDiscovery: true
+ actionDiscovery: true
+ manifest: https://api.example.com/.well-known/agent-ui.json
+ uiInvocation:
+ methods: [templates, customIframe, deepLinks]
+ chainingSupported: true
+ events:
+ supported: [formSubmitted, actionClicked, uiDismissed]
+ delivery: callback
+ permissions:
+ canInvokeTemplates: true
+ canOpenCustomUI: true
+ userApprovalRequired:
+ forActions: true
+ forDataAccess: false
+```
+
+### Agent Capabilities Summary Object
+
+High-level agent interaction capabilities.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| templateInvocation | `boolean` | Agent can invoke pre-defined UI templates. |
+| customUISupport | `boolean` | Agent can open custom UI (iframe). |
+| eventCallbacks | `boolean` | Agent can receive UI events. |
+| actionChaining | `boolean` | Agent can chain multiple UI interactions. |
+
+### Agent Protocol Object
+
+A supported agent protocol.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| name | `string` | **REQUIRED**. Protocol name. Values include: `mcp`, `openai-functions`, `anthropic-tools`, `langchain-tools`, `custom`. |
+| version | `string` | Protocol version. |
+| package | `string` | Package providing the protocol implementation. |
+| schemaFormat | `string` | Schema format for function/tool definitions. Values: `openapi`, `jsonSchema`, `custom`. |
+| documentation | `string` | URI to protocol documentation. |
+
+#### Agent Protocol Object Example
+
+```yaml
+protocols:
+ - name: mcp
+ version: "1.0"
+ package: "@modelcontextprotocol/sdk"
+ schemaFormat: jsonSchema
+ documentation: https://spec.modelcontextprotocol.io
+ - name: openai-functions
+ version: "1.0"
+ schemaFormat: openapi
+ documentation: https://platform.openai.com/docs/guides/function-calling
+```
+
+### Agent Discovery Object
+
+How agents discover UI capabilities.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| templateDiscovery | `boolean` | Agent can query available UI templates. |
+| actionDiscovery | `boolean` | Agent can query available actions. |
+| manifest | `string` | URI to agent UI manifest/schema. |
+
+### Agent Context Object
+
+Context passing to agents.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| available | [`string`] | Available context types (e.g., `conversationHistory`, `userIdentity`, `currentDocument`). |
+| format | `string` | Serialization format. Default: `json`. |
+| piiFiltering | `string` | PII filtering mode. Values: `automatic`, `manual`, `none`. |
+
+#### Agent Context Object Example
+
+```yaml
+context:
+ available:
+ - conversationHistory
+ - userIdentity
+ - currentDocument
+ - workflowState
+ format: json
+ piiFiltering: automatic
+```
+
+### UI Invocation Object
+
+How agents invoke UI.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| methods | [`string`] | Available invocation methods. Values include: `templates`, `customIframe`, `deepLinks`. |
+| chainingSupported | `boolean` | Whether chaining multiple interactions is supported. |
+| interactionTimeout | `integer` | Timeout for interactions in seconds. |
+| cancellationSupported | `boolean` | Whether interactions can be cancelled. |
+
+### Agent Events Object
+
+Events sent back to agents.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| supported | [`string`] | Supported event types (e.g., `formSubmitted`, `actionClicked`, `uiDismissed`, `errorOccurred`). |
+| delivery | `string` | Event delivery method. Values: `callback`, `webhook`, `polling`. |
+
+### Agent Permissions Object
+
+Agent permission model.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| canInvokeTemplates | `boolean` | Agent can invoke UI templates. |
+| canOpenCustomUI | `boolean` | Agent can open custom UI. |
+| canAccessUserData | `boolean` | Agent can access user data. |
+| canPerformActions | `boolean` | Agent can perform actions (not just show UI). |
+| userApprovalRequired | [User Approval Object](#userApprovalObject) | When user approval is required. |
+
+### User Approval Object
+
+When user approval is required.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| forActions | `boolean` | User must approve actions. |
+| forDataAccess | `boolean` | User must approve data access. |
+
+### Agent Templates Object
+
+Pre-declared UI templates the agent can invoke.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| supported | [`string`] | Template types supported by the host. |
+| definitions | Map[`string`, [Agent UI Template Object](#agentUiTemplateObject)] | Template definitions with their schemas. |
+
+#### Agent Templates Object Example
+
+```yaml
+templates:
+ supported:
+ - form
+ - approval
+ - display
+ - picker
+ definitions:
+ documentApproval:
+ name: documentApproval
+ description: Request user approval for a document action
+ inputSchema:
+ type: object
+ properties:
+ documentTitle:
+ type: string
+ action:
+ type: string
+ enum: [sign, review, approve]
+ deadline:
+ type: string
+ format: date-time
+ outputSchema:
+ type: object
+ properties:
+ approved:
+ type: boolean
+ comments:
+ type: string
+ rendering:
+ type: platform
+ component: ApprovalCard
+ interactivity:
+ submitButton: true
+ cancelButton: true
+ events: [submitted, cancelled]
+```
+
+### Agent UI Template Object
+
+Definition of a pre-declared agent UI template.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| name | `string` | Template identifier. |
+| description | `string` | What this template is used for. |
+| inputSchema | `object` | JSON Schema for template input data. |
+| outputSchema | `object` | JSON Schema for template output (user response). |
+| rendering | [Template Rendering Object](#templateRenderingObject) | How the template is rendered. |
+| interactivity | [Template Interactivity Object](#templateInteractivityObject) | Interactive elements. |
+
+### Template Rendering Object
+
+How a template is rendered.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| type | `string` | Rendering strategy. Values: `platform`, `jsonForms`, `custom`. |
+| component | `string` | Platform component used for rendering. |
+
+### Template Interactivity Object
+
+Interactive elements of a template.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| submitButton | `boolean` | Has a submit action. |
+| cancelButton | `boolean` | Has a cancel action. |
+| events | [`string`] | Events this template can emit. |
+
+### Custom UI Object
+
+Custom iframe fallback for complex UI needs.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| allowed | `boolean` | Whether custom iframe UI is supported. Default: `true`. |
+| sandboxAttributes | [`string`] | iframe sandbox attributes for custom UI. |
+| sizeConstraints | [Size Constraints Object](#sizeConstraintsObject) | Size constraints for custom UI. |
+
+### Size Constraints Object
+
+Size constraints for custom UI iframes.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| minWidth | `integer` | Minimum width in pixels. |
+| maxWidth | `integer` | Maximum width in pixels. |
+| minHeight | `integer` | Minimum height in pixels. |
+| maxHeight | `integer` | Maximum height in pixels. |
+| resizable | `boolean` | Whether element can be resized dynamically. |
+
+### Agent Communication Object
+
+How agent and UI communicate.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| protocol | `string` | Primary communication protocol. Values: `jsonRpc`, `postMessage`, `mcp`. Default: `jsonRpc`. |
+| channels | [`string`] | Communication channels available. |
+
+### Agent Capabilities Object
+
+What the agent can do through the UI.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| invokeTemplates | `boolean` | Can invoke pre-declared templates. Default: `true`. |
+| openCustomUI | `boolean` | Can open custom iframe UI. Default: `true`. |
+| receiveEvents | `boolean` | Can receive UI events (clicks, submissions). Default: `true`. |
+| closeUI | `boolean` | Can programmatically close UI. Default: `true`. |
+| chainInteractions | `boolean` | Can chain multiple UI interactions. Default: `true`. |
+
+### Specification Extensions
+
+While the Fenestra Specification tries to accommodate most use cases, additional data can be added to extend the specification at certain points.
+
+The extensions properties are implemented as patterned fields that are always prefixed by `x-`.
+
+| Field Pattern | Type | Description |
+|---|---|---|
+| ^x- | Any | Allows extensions to the Fenestra Schema. The field name MUST begin with `x-`, for example, `x-internal-id`. Field names beginning with `x-oai-` and `x-oas-` are reserved for uses defined by the [OpenAPI Initiative](https://www.openapis.org/). The value can be any valid JSON value (`null`, a primitive, an array, or an object). |
+
+The extensions may or may not be supported by the available tooling, but those may be extended as well to add requested support (if tools are internal or open-source).
+
+## Complete Example
+
+```yaml
+fenestra: "0.1.0"
+info:
+ title: DocuSign Platform UI
+ version: "1.0.0"
+ description: Fenestra description for DocuSign's agent-driven UI platform
+
+agentInteraction:
+ capabilities:
+ templateInvocation: true
+ customUISupport: true
+ eventCallbacks: true
+ actionChaining: true
+
+ protocols:
+ - name: mcp
+ version: "1.0"
+ package: "@docusign/mcp-server"
+ schemaFormat: jsonSchema
+ documentation: https://developers.docusign.com/docs/mcp
+ - name: openai-functions
+ version: "1.0"
+ schemaFormat: openapi
+ documentation: https://developers.docusign.com/docs/openai
+
+ discovery:
+ templateDiscovery: true
+ actionDiscovery: true
+ manifest: https://api.docusign.com/.well-known/agent-capabilities.json
+
+ context:
+ available:
+ - userIdentity
+ - currentEnvelope
+ - organizationContext
+ format: json
+ piiFiltering: automatic
+
+ uiInvocation:
+ methods:
+ - templates
+ - customIframe
+ chainingSupported: true
+ interactionTimeout: 300
+ cancellationSupported: true
+
+ events:
+ supported:
+ - formSubmitted
+ - actionClicked
+ - uiDismissed
+ - errorOccurred
+ - envelopeSigned
+ delivery: callback
+
+ permissions:
+ canInvokeTemplates: true
+ canOpenCustomUI: true
+ canAccessUserData: true
+ canPerformActions: true
+ userApprovalRequired:
+ forActions: true
+ forDataAccess: false
+
+# Agent UI extension point using these capabilities
+extensionPoints:
+ - id: signing-flow-agent
+ name: Agent-Driven Signing Flow
+ type: embedded
+ extensionType: agentUI
+ extensionTypeConfig:
+ templates:
+ supported:
+ - documentPreview
+ - signatureRequest
+ - recipientPicker
+ - approvalFlow
+ definitions:
+ signatureRequest:
+ name: signatureRequest
+ description: Request document signature from user
+ inputSchema:
+ type: object
+ required:
+ - documentId
+ - documentTitle
+ properties:
+ documentId:
+ type: string
+ documentTitle:
+ type: string
+ signers:
+ type: array
+ items:
+ type: object
+ properties:
+ name:
+ type: string
+ email:
+ type: string
+ role:
+ type: string
+ dueDate:
+ type: string
+ format: date-time
+ outputSchema:
+ type: object
+ properties:
+ action:
+ type: string
+ enum: [sign, decline, delegate]
+ delegateEmail:
+ type: string
+ comments:
+ type: string
+ rendering:
+ type: platform
+ component: SignatureRequestCard
+ interactivity:
+ submitButton: true
+ cancelButton: true
+ events:
+ - submitted
+ - cancelled
+ - documentViewed
+
+ customUI:
+ allowed: true
+ sandboxAttributes:
+ - allow-scripts
+ - allow-forms
+ - allow-same-origin
+ sizeConstraints:
+ minWidth: 400
+ maxWidth: 800
+ minHeight: 300
+ maxHeight: 600
+ resizable: true
+
+ communication:
+ protocol: jsonRpc
+ channels:
+ - ui-events
+ - document-updates
+
+ agentCapabilities:
+ invokeTemplates: true
+ openCustomUI: true
+ receiveEvents: true
+ closeUI: true
+ chainInteractions: true
+```
+
+## Appendix A: Revision History
+
+| Version | Date | Notes |
+|---------|------|-------|
+| 0.1.0 | 2024-12-27 | Initial draft - extracted from Fenestra Core Specification |
diff --git a/specs/fenestra/versions/extensions/compliance/0.1.0.md b/specs/fenestra/versions/extensions/compliance/0.1.0.md
new file mode 100644
index 0000000..bafd9cb
--- /dev/null
+++ b/specs/fenestra/versions/extensions/compliance/0.1.0.md
@@ -0,0 +1,564 @@
+# Fenestra Compliance Extension
+
+## Version 0.1.0
+
+The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP 14](https://tools.ietf.org/html/bcp14) [RFC2119](https://tools.ietf.org/html/rfc2119) [RFC8174](https://tools.ietf.org/html/rfc8174) when, and only when, they appear in all capitals, as shown here.
+
+This document is licensed under [The Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.html).
+
+## Abstract
+
+The Fenestra Compliance Extension provides vocabulary for describing platform accessibility, security, and privacy compliance posture, as well as shared responsibility models between platforms and extension developers. This extension enables machine-readable documentation of compliance standards, certification requirements, and the division of compliance responsibilities in platform extension ecosystems.
+
+## Introduction
+
+Modern software platforms face complex compliance requirements spanning accessibility standards (WCAG, Section 508), security certifications (SOC2, ISO 27001), and privacy regulations (GDPR, CCPA). When platforms enable third-party developers to build extensions, apps, or integrations, compliance responsibilities become shared between the platform and developers.
+
+The Fenestra Compliance Extension standardizes the description of:
+
+1. **Accessibility Compliance** - Standards the platform meets and requires of extensions
+2. **Security Compliance** - Platform certifications and extension security requirements
+3. **Privacy Compliance** - Privacy regulations supported and data handling requirements
+4. **Shared Responsibility** - Clear delineation of who handles what aspects of compliance
+
+A Fenestra Compliance description can be used by:
+- **Extension developers** to understand compliance requirements before building
+- **Security teams** to assess platform risk and compliance posture
+- **Procurement teams** to evaluate vendor compliance during purchasing decisions
+- **Legal teams** to understand data processing agreements and privacy requirements
+- **AI assistants** to generate compliant extension code that meets platform requirements
+
+### Use Cases
+
+**Accessibility Planning**: A developer building a Salesforce extension can query the Fenestra Description to learn that WCAG 2.1 AA compliance is required for marketplace apps and that an accessibility audit must be passed before publication.
+
+**Security Assessment**: A security team evaluating HubSpot can review its Fenestra Description to see that the platform holds SOC2 Type II and ISO 27001 certifications, requires HTTPS for all extensions, and mandates security reviews for public apps.
+
+**Privacy Due Diligence**: A legal team can review a platform's Fenestra Description to understand whether it's GDPR compliant, whether data residency options are available, and what consent management mechanisms are in place.
+
+**Shared Responsibility Clarity**: An extension developer can clearly see which security and privacy obligations are handled by the platform (e.g., infrastructure security, user authentication) versus which must be implemented in the extension (e.g., extension-specific accessibility, extension data handling).
+
+## Relationship to Fenestra Core
+
+This extension adds an optional `compliance` field to the Fenestra Object defined in the Fenestra core specification.
+
+```yaml
+fenestra: "0.1.0"
+info:
+ title: Example Platform
+ version: "1.0.0"
+compliance:
+ accessibility:
+ platformStandard: WCAG 2.1 AA
+ extensionRequirements:
+ standard: WCAG 2.1 AA
+ scope: marketplace
+ security:
+ platformCertifications:
+ - SOC2 Type II
+ - ISO 27001
+ privacy:
+ platformCompliance:
+ gdpr: true
+ ccpa: true
+```
+
+The `compliance` field is OPTIONAL in Fenestra Descriptions. Platforms MAY provide partial compliance information (e.g., only accessibility, or only security) as appropriate for their context.
+
+## Security Considerations
+
+### Compliance Claims are Descriptive, Not Certifying
+
+The Fenestra Compliance Extension provides vocabulary for describing compliance posture, but **does not certify compliance**. Consumers of Fenestra Descriptions SHOULD understand:
+
+1. **Fenestra Descriptions are not self-certifying.** A document claiming `compliance.security.platformCertifications: ["SOC2 Type II"]` does not prove SOC2 compliance. Consumers requiring compliance verification SHOULD request audit reports through appropriate channels.
+
+2. **Compliance requires ongoing practices.** Listing `gdpr: true` indicates the platform's self-assessment that it complies with GDPR. Actual GDPR compliance requires ongoing operational practices including data processing agreements, privacy impact assessments, and breach notification procedures—not just a boolean flag in a specification document.
+
+3. **Extension requirements are policies, not enforcement.** When a platform specifies `extensionRequirements.standard: "WCAG 2.1 AA"`, it is stating a policy requirement. Whether this requirement is enforced through automated testing, manual review, or developer self-certification depends on the platform's review processes, which are not described in the Fenestra Description.
+
+4. **Tooling should validate claims where possible.** Tools processing Fenestra Descriptions SHOULD validate compliance claims where possible (e.g., checking that documentation URIs resolve) rather than trusting all assertions.
+
+### Trust Model
+
+Fenestra Descriptions are assertions by platforms about their capabilities and requirements. For compliance-sensitive use cases:
+
+**Recommendations for Compliance-Sensitive Environments:**
+1. Use Fenestra Descriptions as a starting point for vendor assessment, not as sufficient evidence.
+2. Request supporting documentation (SOC2 reports, DPAs, VPATs) through appropriate channels.
+3. Conduct independent security assessments for high-risk integrations.
+4. Verify compliance claims through audit reports, certifications, and attestations.
+5. Review legal contracts for binding compliance commitments.
+
+**Platform Authors SHOULD:**
+- Provide accurate compliance information. Misrepresenting security certifications or compliance status may have legal consequences.
+- Update compliance information promptly when certifications change or expire.
+- Provide URIs to supporting documentation where appropriate.
+- Clearly document shared responsibility boundaries.
+
+**Extension Developers SHOULD:**
+- Treat compliance requirements as minimum standards.
+- Implement defense-in-depth security practices beyond platform requirements.
+- Obtain independent compliance validation when building for regulated industries.
+- Review platform contracts for legal compliance obligations beyond the Fenestra Description.
+
+### Shared Responsibility Model
+
+The `sharedResponsibility` object describes the division of compliance obligations between platform and developer. This information is **informational, not legally binding**. Legal responsibility is determined by:
+
+- Platform terms of service and developer agreements
+- Data processing agreements (DPAs)
+- Business associate agreements (BAAs) for HIPAA compliance
+- Regulatory obligations that apply regardless of contractual terms
+
+The shared responsibility description in a Fenestra document provides a high-level summary but does not replace legal contracts.
+
+### Privacy and Data Handling
+
+Fields like `dataHandling.piiAllowed` and `userRights.dataExportSupported` describe platform capabilities and policies:
+
+- **Platform Capabilities**: What the platform infrastructure supports (e.g., data residency in specific regions).
+- **Platform Policies**: What the platform requires of extensions (e.g., privacy policy required).
+- **Not Legal Obligations**: These fields do not create legal obligations or substitute for data processing agreements.
+
+Developers building extensions that process sensitive data SHOULD:
+1. Review platform data processing agreements (DPAs).
+2. Conduct data protection impact assessments (DPIAs) as required by regulation.
+3. Implement appropriate technical and organizational measures.
+4. Not rely solely on platform-provided security controls.
+
+## Schema
+
+In the following description, if a field is not explicitly **REQUIRED** or described with a MUST or SHALL, it can be considered OPTIONAL.
+
+### Compliance Object
+
+Accessibility, security, and privacy compliance information.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| accessibility | [Accessibility Compliance Object](#accessibilityComplianceObject) | Accessibility compliance information. |
+| security | [Security Compliance Object](#securityComplianceObject) | Security compliance information. |
+| privacy | [Privacy Compliance Object](#privacyComplianceObject) | Privacy compliance information. |
+| sharedResponsibility | [Shared Responsibility Object](#sharedResponsibilityObject) | What platform handles vs what developer handles. |
+
+This object MAY be extended with Specification Extensions.
+
+#### Compliance Object Example
+
+```yaml
+compliance:
+ accessibility:
+ platformStandard: WCAG 2.1 AA
+ extensionRequirements:
+ standard: WCAG 2.1 AA
+ scope: marketplace
+ auditRequired: true
+ platformProvides:
+ accessibleComponents: true
+ keyboardNavigation: true
+ focusManagement: true
+ security:
+ platformCertifications:
+ - SOC2 Type II
+ - ISO 27001
+ extensionRequirements:
+ httpsOnly: true
+ cspCompliance: true
+ securityReview:
+ required: true
+ scope: marketplace
+ privacy:
+ platformCompliance:
+ gdpr: true
+ ccpa: true
+ dataResidency:
+ available: true
+ regions: [US, EU, AU]
+ extensionRequirements:
+ privacyPolicyRequired: true
+ consentManagement: platform
+ sharedResponsibility:
+ platformHandles:
+ - Infrastructure security
+ - Platform accessibility
+ - User authentication
+ developerHandles:
+ - Extension accessibility
+ - Extension data handling
+```
+
+### Accessibility Compliance Object
+
+Accessibility compliance information.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| platformStandard | `string` | Standard the platform itself meets (e.g., `WCAG 2.1 AA`, `Section 508`). |
+| extensionRequirements | [Accessibility Extension Requirements Object](#accessibilityExtensionRequirementsObject) | What's required of extensions. |
+| platformProvides | [Platform Accessibility Object](#platformAccessibilityObject) | What the platform provides to help developers. |
+| documentation | `string` | URI to accessibility documentation. |
+
+#### Accessibility Compliance Object Example
+
+```yaml
+accessibility:
+ platformStandard: WCAG 2.1 AA
+ extensionRequirements:
+ standard: WCAG 2.1 AA
+ scope: marketplace
+ auditRequired: true
+ platformProvides:
+ accessibleComponents: true
+ screenReaderTested: true
+ keyboardNavigation: true
+ focusManagement: true
+ ariaAttributesHandled: true
+ documentation: https://developers.example.com/accessibility
+```
+
+### Accessibility Extension Requirements Object
+
+Accessibility requirements for extensions.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| standard | `string` | Required standard. Values MUST be one of: `none`, `WCAG 2.0 A`, `WCAG 2.0 AA`, `WCAG 2.1 A`, `WCAG 2.1 AA`, `WCAG 2.2 AA`, `Section 508`. |
+| scope | `string` | Which apps this applies to. Values MUST be one of: `all`, `marketplace`, `public`, `none`. |
+| auditRequired | `boolean` | Whether accessibility audit is required. Default: `false`. |
+
+#### Accessibility Extension Requirements Object Example
+
+```yaml
+extensionRequirements:
+ standard: WCAG 2.1 AA
+ scope: marketplace
+ auditRequired: true
+```
+
+### Platform Accessibility Object
+
+What the platform provides for accessibility.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| accessibleComponents | `boolean` | Built-in components are accessible. |
+| screenReaderTested | `boolean` | Components tested with screen readers. |
+| keyboardNavigation | `boolean` | Keyboard navigation supported. |
+| focusManagement | `boolean` | Focus management handled. |
+| ariaAttributesHandled | `boolean` | ARIA attributes handled on platform components. |
+
+#### Platform Accessibility Object Example
+
+```yaml
+platformProvides:
+ accessibleComponents: true
+ screenReaderTested: true
+ keyboardNavigation: true
+ focusManagement: true
+ ariaAttributesHandled: true
+```
+
+### Security Compliance Object
+
+Security compliance information.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| platformCertifications | [`string`] | Platform's security certifications (e.g., `SOC2 Type II`, `ISO 27001`, `HIPAA`). |
+| extensionRequirements | [Security Extension Requirements Object](#securityExtensionRequirementsObject) | Security requirements for extensions. |
+| documentation | `string` | URI to security documentation. |
+
+#### Security Compliance Object Example
+
+```yaml
+security:
+ platformCertifications:
+ - SOC2 Type II
+ - ISO 27001
+ - HIPAA
+ extensionRequirements:
+ httpsOnly: true
+ cspCompliance: true
+ noInlineScripts: true
+ securityReview:
+ required: true
+ scope: marketplace
+ dataHandling:
+ piiAllowed: true
+ piiMustEncrypt: true
+ dataRetentionPolicy: required
+ documentation: https://developers.example.com/security
+```
+
+### Security Extension Requirements Object
+
+Security requirements for extensions.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| httpsOnly | `boolean` | Whether HTTPS is required. Default: `true`. |
+| cspCompliance | `boolean` | Whether CSP compliance is required. |
+| noInlineScripts | `boolean` | Whether inline scripts are prohibited. |
+| noExternalScripts | `boolean` | Whether external scripts are prohibited. Default: `false`. |
+| securityReview | [Review Requirement Object](#reviewRequirementObject) | Security review requirements. |
+| dataHandling | [Data Handling Object](#dataHandlingObject) | Data handling requirements. |
+
+#### Security Extension Requirements Object Example
+
+```yaml
+extensionRequirements:
+ httpsOnly: true
+ cspCompliance: true
+ noInlineScripts: true
+ noExternalScripts: false
+ securityReview:
+ required: true
+ scope: marketplace
+ dataHandling:
+ piiAllowed: true
+ piiMustEncrypt: true
+ dataRetentionPolicy: required
+```
+
+### Review Requirement Object
+
+Review requirements for extensions.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| required | `boolean` | Whether review is required. |
+| scope | `string` | Which apps require review. Values MUST be one of: `all`, `marketplace`, `public`, `none`. |
+
+#### Review Requirement Object Example
+
+```yaml
+securityReview:
+ required: true
+ scope: marketplace
+```
+
+### Data Handling Object
+
+Data handling requirements.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| piiAllowed | `boolean` | Whether PII can be processed. |
+| piiMustEncrypt | `boolean` | Whether PII must be encrypted. |
+| dataRetentionPolicy | `string` | Retention policy requirement. Values MUST be one of: `required`, `recommended`, `none`. |
+
+#### Data Handling Object Example
+
+```yaml
+dataHandling:
+ piiAllowed: true
+ piiMustEncrypt: true
+ dataRetentionPolicy: required
+```
+
+### Privacy Compliance Object
+
+Privacy compliance information.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| platformCompliance | [Platform Privacy Object](#platformPrivacyObject) | Platform's privacy compliance. |
+| dataResidency | [Data Residency Object](#dataResidencyObject) | Data residency options. |
+| extensionRequirements | [Privacy Extension Requirements Object](#privacyExtensionRequirementsObject) | Privacy requirements for extensions. |
+| userRights | [User Rights Object](#userRightsObject) | User rights support. |
+| documentation | `string` | URI to privacy documentation. |
+
+#### Privacy Compliance Object Example
+
+```yaml
+privacy:
+ platformCompliance:
+ gdpr: true
+ ccpa: true
+ dataResidency:
+ available: true
+ regions: [US, EU, AU]
+ extensionRequirements:
+ privacyPolicyRequired: true
+ consentManagement: platform
+ dataProcessingAgreement: required
+ userRights:
+ dataExportSupported: true
+ dataDeletionSupported: true
+ documentation: https://developers.example.com/privacy
+```
+
+### Platform Privacy Object
+
+Platform's privacy compliance.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| gdpr | `boolean` | Platform is GDPR compliant. |
+| ccpa | `boolean` | Platform is CCPA compliant. |
+
+#### Platform Privacy Object Example
+
+```yaml
+platformCompliance:
+ gdpr: true
+ ccpa: true
+```
+
+### Data Residency Object
+
+Data residency options.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| available | `boolean` | Whether data residency options are available. |
+| regions | [`string`] | Available regions (e.g., `US`, `EU`, `AU`). |
+
+#### Data Residency Object Example
+
+```yaml
+dataResidency:
+ available: true
+ regions: [US, EU, AU, APAC]
+```
+
+### Privacy Extension Requirements Object
+
+Privacy requirements for extensions.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| privacyPolicyRequired | `boolean` | Whether privacy policy is required. |
+| consentManagement | `string` | Who manages consent. Values MUST be one of: `platform`, `developer`, `both`. |
+| dataProcessingAgreement | `string` | DPA requirement. Values MUST be one of: `required`, `recommended`, `none`. |
+
+#### Privacy Extension Requirements Object Example
+
+```yaml
+extensionRequirements:
+ privacyPolicyRequired: true
+ consentManagement: platform
+ dataProcessingAgreement: required
+```
+
+### User Rights Object
+
+User rights support.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| dataExportSupported | `boolean` | Data export is supported. |
+| dataDeletionSupported | `boolean` | Data deletion is supported. |
+
+#### User Rights Object Example
+
+```yaml
+userRights:
+ dataExportSupported: true
+ dataDeletionSupported: true
+```
+
+### Shared Responsibility Object
+
+What platform handles vs what developer handles.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| platformHandles | [`string`] | What the platform is responsible for. |
+| developerHandles | [`string`] | What the developer is responsible for. |
+| documentation | `string` | URI to shared responsibility documentation. |
+
+#### Shared Responsibility Object Example
+
+```yaml
+sharedResponsibility:
+ platformHandles:
+ - Infrastructure security
+ - Network security
+ - Platform accessibility (built-in components)
+ - User authentication and authorization
+ - Data encryption at rest
+ - Data encryption in transit
+ - SOC2 compliance for platform infrastructure
+ - GDPR compliance for platform operations
+ developerHandles:
+ - Extension code security
+ - Extension accessibility compliance
+ - Extension data handling practices
+ - Extension-specific privacy policies
+ - Third-party service integrations
+ - Custom component accessibility
+ - Sensitive data encryption in extension code
+ documentation: https://developers.example.com/shared-responsibility
+```
+
+## Specification Extensions
+
+While the Fenestra Specification tries to accommodate most use cases, additional data can be added to extend the specification at certain points.
+
+The extensions properties are implemented as patterned fields that are always prefixed by `x-`.
+
+| Field Pattern | Type | Description |
+|---|---|---|
+| ^x- | Any | Allows extensions to the Fenestra Schema. The field name MUST begin with `x-`, for example, `x-internal-id`. Field names beginning with `x-oai-` and `x-oas-` are reserved for uses defined by the [OpenAPI Initiative](https://www.openapis.org/). The value can be any valid JSON value (`null`, a primitive, an array, or an object). |
+
+The extensions may or may not be supported by the available tooling, but those may be extended as well to add requested support (if tools are internal or open-source).
+
+### Example with Extensions
+
+```yaml
+compliance:
+ accessibility:
+ platformStandard: WCAG 2.1 AA
+ x-wcag-conformance-report: https://example.com/vpat.pdf
+ x-last-audit-date: "2024-11-15"
+ security:
+ platformCertifications:
+ - SOC2 Type II
+ - ISO 27001
+ x-certification-expiry:
+ soc2: "2025-06-30"
+ iso27001: "2025-12-31"
+ x-pentest-frequency: quarterly
+ privacy:
+ platformCompliance:
+ gdpr: true
+ ccpa: true
+ x-dpo-contact: dpo@example.com
+ x-privacy-shield: false
+```
+
+## Appendix A: Revision History
+
+| Version | Date | Notes |
+|---------|------|-------|
+| 0.1.0 | 2024-12-27 | Initial draft of Compliance Extension |
diff --git a/specs/fenestra/versions/extensions/declarative/0.1.0.md b/specs/fenestra/versions/extensions/declarative/0.1.0.md
new file mode 100644
index 0000000..ab40fae
--- /dev/null
+++ b/specs/fenestra/versions/extensions/declarative/0.1.0.md
@@ -0,0 +1,363 @@
+# Fenestra Declarative Extension
+
+## Version 0.1.0
+
+The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP 14](https://tools.ietf.org/html/bcp14) [RFC2119](https://tools.ietf.org/html/rfc2119) [RFC8174](https://tools.ietf.org/html/rfc8174) when, and only when, they appear in all capitals, as shown here.
+
+This document is licensed under [The Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.html).
+
+## Abstract
+
+The Fenestra Declarative Extension provides vocabulary for describing JSON-based UI schema languages (Slack Block Kit, Microsoft Adaptive Cards, etc.) and mapping their elements to Fenestra components. This extension enables machine-readable documentation of how platforms use declarative JSON schemas for UI rendering, how these schemas are delivered, and how their elements correspond to standard UI component patterns.
+
+## Introduction
+
+Many modern platforms provide UI extension capabilities through declarative JSON schemas rather than imperative code. Developers return structured JSON from API endpoints, and the platform handles all rendering, interaction, and lifecycle management. This pattern is exemplified by:
+
+- **Slack Block Kit**: Developers return JSON blocks from endpoints; Slack renders the UI in messages and modals
+- **Microsoft Adaptive Cards**: Cross-platform JSON schema for cards that render consistently across Teams, Outlook, and other hosts
+- **Discord Message Components**: JSON-based buttons, select menus, and modals for bot interactions
+- **Zendesk App Framework**: JSON ticket and sidebar UIs for customer service integrations
+
+The Declarative Extension standardizes the description of these JSON-based UI schema languages, enabling:
+
+- **Schema discovery**: What JSON format does the platform expect?
+- **Element mapping**: How do platform-specific elements relate to common UI patterns?
+- **Delivery mechanisms**: How is the JSON transmitted (HTTP response, webhook, WebSocket)?
+- **Validation tooling**: What tools exist for testing and debugging schemas?
+
+This extension complements the `jsonResponse` extension type defined in Fenestra Core by providing detailed schema definitions and element mappings.
+
+## Relationship to Fenestra Core
+
+This extension adds an optional `declarativeSchemas` field to the [Fenestra Object](../../0.1.0.md#fenestraObject) in the Fenestra Core specification.
+
+The `declarativeSchemas` field is a map of schema identifiers to Declarative Schema Objects. Each object describes one JSON-based UI schema language that the platform supports.
+
+**Usage in Fenestra Core:**
+
+```yaml
+fenestra: "0.1.0"
+info:
+ title: Slack Platform
+ version: "1.0.0"
+
+# Core specification fields...
+
+declarativeSchemas:
+ block-kit:
+ name: Slack Block Kit
+ version: "1.0"
+ schemaUrl: https://api.slack.com/reference/block-kit/blocks
+ documentation: https://api.slack.com/block-kit
+ delivery:
+ method: httpResponse
+ contentType: application/json
+ elementMappings:
+ section:
+ fenestraComponent: Card
+ notes: Container with text and optional accessory
+ button:
+ fenestraComponent: Button
+ validator:
+ tool: Block Kit Builder
+ url: https://app.slack.com/block-kit-builder
+```
+
+The declarative schema is typically used in conjunction with the `jsonResponse` extension type, which specifies that developers return JSON and the platform handles rendering:
+
+```yaml
+extensionPoints:
+ - id: message-actions
+ name: Message Actions
+ type: contextMenu
+ extensionType: jsonResponse
+ extensionTypeConfig:
+ schema:
+ format: slack.blocks # References the declarative schema
+ version: "1.0"
+ schemaUrl: https://api.slack.com/reference/block-kit/blocks
+```
+
+## Schema
+
+In the following description, if a field is not explicitly **REQUIRED** or described with a MUST or SHALL, it can be considered OPTIONAL.
+
+### Declarative Schema Object
+
+Describes a JSON-based UI schema used by the platform (e.g., Slack Block Kit, Adaptive Cards).
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| name | `string` | **REQUIRED**. Human-readable name of the schema (e.g., "Slack Block Kit"). |
+| version | `string` | Schema version. |
+| schemaUrl | `string` | URI to the JSON Schema or specification document. |
+| documentation | `string` | URI to developer documentation. |
+| delivery | [Delivery Object](#deliveryObject) | How JSON responses are delivered to the platform. |
+| elementMappings | Map[`string`, [Element Mapping Object](#elementMappingObject)] | Optional mappings from JSON elements to Fenestra components. |
+| validator | [Validator Tool Object](#validatorToolObject) | Validation/testing tools if available. |
+
+This object MAY be extended with [Specification Extensions](../../0.1.0.md#specificationExtensions).
+
+#### Declarative Schema Object Example
+
+```yaml
+declarativeSchemas:
+ block-kit:
+ name: Slack Block Kit
+ version: "1.0"
+ schemaUrl: https://api.slack.com/reference/block-kit/blocks
+ documentation: https://api.slack.com/block-kit
+ delivery:
+ method: httpResponse
+ contentType: application/json
+ elementMappings:
+ section:
+ fenestraComponent: Card
+ notes: Container with text and optional accessory
+ button:
+ fenestraComponent: Button
+ input:
+ fenestraComponent: Input
+ notes: Text input, select menu, or other input element
+ divider:
+ fenestraComponent: Divider
+ validator:
+ tool: Block Kit Builder
+ url: https://app.slack.com/block-kit-builder
+```
+
+#### Microsoft Adaptive Cards Example
+
+```yaml
+declarativeSchemas:
+ adaptive-cards:
+ name: Microsoft Adaptive Cards
+ version: "1.5"
+ schemaUrl: https://adaptivecards.io/schemas/adaptive-card.json
+ documentation: https://adaptivecards.io/explorer/
+ delivery:
+ method: httpResponse
+ contentType: application/json
+ elementMappings:
+ TextBlock:
+ fenestraComponent: Text
+ Image:
+ fenestraComponent: Image
+ Input.Text:
+ fenestraComponent: Input
+ Input.ChoiceSet:
+ fenestraComponent: Select
+ Action.Submit:
+ fenestraComponent: Button
+ notes: Primary action button
+ Container:
+ fenestraComponent: Card
+ validator:
+ tool: Adaptive Cards Designer
+ url: https://adaptivecards.io/designer/
+```
+
+### Delivery Object
+
+How JSON responses are delivered to the platform.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| method | `string` | Delivery method. Values MUST be one of: `httpResponse`, `webhook`, `websocket`. |
+| contentType | `string` | Content-Type for responses. Default: `application/json`. |
+
+#### Delivery Object Examples
+
+**HTTP Response Delivery:**
+
+```yaml
+delivery:
+ method: httpResponse
+ contentType: application/json
+```
+
+In this pattern, the platform makes an HTTP request to the developer's endpoint, and the developer returns the JSON schema in the response body.
+
+**Webhook Delivery:**
+
+```yaml
+delivery:
+ method: webhook
+ contentType: application/json
+```
+
+In this pattern, the developer proactively sends JSON schemas to the platform's webhook endpoint (e.g., Slack incoming webhooks, Discord webhooks).
+
+**WebSocket Delivery:**
+
+```yaml
+delivery:
+ method: websocket
+ contentType: application/json
+```
+
+In this pattern, JSON schemas are transmitted over a persistent WebSocket connection between the developer's application and the platform.
+
+### Element Mapping Object
+
+Maps a JSON element to a Fenestra component.
+
+Element mappings are optional but help establish semantic relationships between platform-specific schema elements and universal UI component patterns. These mappings enable:
+
+- **Cross-platform understanding**: Recognizing that Slack's `section` and Adaptive Cards' `Container` serve similar purposes
+- **Code generation**: Translating from abstract component models to platform-specific schemas
+- **Documentation**: Explaining platform elements in terms of familiar UI concepts
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| fenestraComponent | `string` | Reference to a component in `componentCatalog.components` in the main Fenestra Description. |
+| notes | `string` | Additional notes about the mapping. |
+
+#### Element Mapping Object Examples
+
+**Basic Mapping:**
+
+```yaml
+elementMappings:
+ button:
+ fenestraComponent: Button
+```
+
+This indicates that the `button` element in the JSON schema corresponds to the `Button` component in the platform's component catalog.
+
+**Mapping with Notes:**
+
+```yaml
+elementMappings:
+ section:
+ fenestraComponent: Card
+ notes: Container with text and optional accessory element
+ action:
+ fenestraComponent: Button
+ notes: Can be standalone or appear in action blocks
+ input.text:
+ fenestraComponent: Input
+ notes: Single-line text input within a modal
+ input.multiline:
+ fenestraComponent: Textarea
+ notes: Multi-line text input for longer responses
+```
+
+**Complex Platform Example:**
+
+```yaml
+elementMappings:
+ # Discord message components
+ ActionRow:
+ fenestraComponent: ButtonGroup
+ notes: Container for up to 5 buttons or 1 select menu
+ Button:
+ fenestraComponent: Button
+ notes: Supports 5 styles - Primary, Secondary, Success, Danger, Link
+ SelectMenu:
+ fenestraComponent: Select
+ notes: Dropdown with up to 25 options
+ TextInput:
+ fenestraComponent: Input
+ notes: Only available in modals, supports single and multi-line
+ Modal:
+ fenestraComponent: Modal
+ notes: Container for forms with TextInput components
+```
+
+### Validator Tool Object
+
+A validation or testing tool for a declarative schema.
+
+Many platforms provide web-based or CLI tools for validating, previewing, and debugging their JSON schemas. This object documents those tools so developers can discover them through Fenestra Descriptions.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| tool | `string` | Name of the validation tool. |
+| url | `string` | URI to the validation tool. |
+
+#### Validator Tool Object Examples
+
+**Web-based Validator:**
+
+```yaml
+validator:
+ tool: Block Kit Builder
+ url: https://app.slack.com/block-kit-builder
+```
+
+**Multiple Validation Tools:**
+
+While the Validator Tool Object only describes a single tool, platforms with multiple validation options can list additional tools in extension fields:
+
+```yaml
+validator:
+ tool: Adaptive Cards Designer
+ url: https://adaptivecards.io/designer/
+ x-cli-validator:
+ tool: adaptive-cards-cli
+ command: npm install -g @microsoft/adaptivecards-cli
+ x-vscode-extension:
+ tool: Adaptive Cards Studio
+ url: https://marketplace.visualstudio.com/items?itemName=madewithcards.adaptivecardsstudiobeta
+```
+
+**API-based Validator:**
+
+```yaml
+validator:
+ tool: Schema Validation API
+ url: https://api.example.com/validate-schema
+ x-method: POST
+ x-authentication: apiKey
+```
+
+## Security Considerations
+
+### Schema URL Handling
+
+Tooling that fetches schemas from `schemaUrl` fields SHOULD:
+
+- Validate that URIs use HTTPS
+- Implement SSRF protections (block internal IPs, localhost, cloud metadata endpoints)
+- Apply reasonable timeouts
+- Limit redirect following
+
+### Element Mapping Trust
+
+Element mappings are semantic assertions, not security guarantees. A mapping claiming that a platform element corresponds to a `Button` component does not guarantee that the element behaves like a button or has appropriate accessibility attributes.
+
+Tooling SHOULD NOT automatically generate code from element mappings without user review, as incorrect mappings could introduce security vulnerabilities or accessibility issues.
+
+### Validator Tool Safety
+
+Validator tool URLs point to external services. Tooling SHOULD:
+
+- Display validator URLs before opening them
+- Warn users before transmitting sensitive data to validator tools
+- Prefer official validator tools from verified platform domains
+
+Developers SHOULD NOT paste production secrets, credentials, or sensitive user data into web-based validator tools unless they trust the tool provider and have verified the connection is secure.
+
+### JSON Schema Validation
+
+The `schemaUrl` field may point to a JSON Schema definition. Tooling that validates JSON against these schemas SHOULD:
+
+- Disable or sandbox remote `$ref` resolution to prevent SSRF
+- Limit schema complexity to prevent denial-of-service through deeply nested schemas
+- Validate that fetched schemas are well-formed JSON Schema documents
+
+## Appendix A: Revision History
+
+| Version | Date | Notes |
+|---------|------|-------|
+| 0.1.0 | 2024-12-27 | Initial draft extracted from Fenestra Core 0.1.0 |
diff --git a/specs/fenestra/versions/extensions/i18n/0.1.0.md b/specs/fenestra/versions/extensions/i18n/0.1.0.md
new file mode 100644
index 0000000..81c40d0
--- /dev/null
+++ b/specs/fenestra/versions/extensions/i18n/0.1.0.md
@@ -0,0 +1,402 @@
+# Fenestra I18n Extension
+
+## Version 0.1.0
+
+The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP 14](https://tools.ietf.org/html/bcp14) [RFC2119](https://tools.ietf.org/html/rfc2119) [RFC8174](https://tools.ietf.org/html/rfc8174) when, and only when, they appear in all capitals, as shown here.
+
+This document is licensed under [The Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.html).
+
+## Abstract
+
+The Fenestra I18n Extension provides vocabulary for describing platform internationalization capabilities and developer localization requirements. This extension enables platforms to document their multi-language support, locale detection mechanisms, right-to-left (RTL) layout capabilities, and the responsibilities developers have for localizing their extensions.
+
+## Introduction
+
+Internationalization (i18n) is a critical concern for platforms operating in global markets. Different platforms have varying approaches to i18n:
+
+- **Platform-Provided Translations**: Some platforms automatically translate their built-in UI components
+- **Developer Responsibilities**: Platforms may require developers to provide translations for custom content
+- **Locale Detection**: Platforms use different mechanisms to determine user language preferences
+- **RTL Support**: Platforms have varying levels of support for right-to-left languages
+- **Formatting Conventions**: Dates, numbers, and currencies may be formatted by the platform or developer
+
+The Fenestra I18n Extension standardizes the description of these capabilities, enabling:
+- **Documentation generators** to create clear i18n guides for developers
+- **Validation tools** to verify that extensions meet localization requirements
+- **AI assistants** to understand platform i18n patterns and generate compliant code
+- **Code generators** to scaffold projects with appropriate i18n libraries and configurations
+
+## Relationship to Fenestra Core
+
+This extension adds an optional `i18n` field to the Fenestra Object defined in Fenestra Core 0.1.0.
+
+```yaml
+fenestra: "0.1.0"
+info:
+ title: Example Platform
+ version: "1.0.0"
+i18n:
+ # I18n Extension fields defined in this specification
+ platformSupport:
+ enabled: true
+ availableLocales: [en, es, fr]
+ developerRequirements:
+ translationMechanism:
+ format: icu
+```
+
+The `i18n` field is OPTIONAL. Platforms that do not provide internationalization capabilities or do not wish to document them MAY omit this field.
+
+## Schema
+
+### I18n Object
+
+Internationalization capabilities and requirements.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| platformSupport | [I18n Platform Support Object](#i18nPlatformSupportObject) | What the platform provides for internationalization. |
+| componentTranslations | [Component Translations Object](#componentTranslationsObject) | Whether platform-provided components are translated. |
+| developerRequirements | [I18n Developer Requirements Object](#i18nDeveloperRequirementsObject) | What developers must handle for internationalization. |
+| documentation | `string` | URI to i18n documentation. |
+
+This object MAY be extended with [Specification Extensions](#specificationExtensions).
+
+#### I18n Object Example
+
+```yaml
+i18n:
+ platformSupport:
+ enabled: true
+ availableLocales: [en, es, fr, de, ja, pt-BR]
+ localeDetection:
+ method: automatic
+ sources: [userPreference, accountSetting]
+ rtlSupport:
+ enabled: true
+ languages: [ar, he]
+ componentTranslations:
+ provided: true
+ scope: all
+ developerRequirements:
+ translationMechanism:
+ format: icu
+ bundleLocation: embedded
+ marketplaceRequirement:
+ required: false
+ formatting:
+ dates: platform
+ numbers: platform
+ currencies: developer
+ documentation: https://developers.example.com/docs/i18n
+```
+
+### I18n Platform Support Object
+
+What the platform provides for internationalization.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| enabled | `boolean` | Whether i18n is supported. Default: `false`. |
+| availableLocales | [`string`] | Languages the platform UI is available in (BCP 47 tags). |
+| localeDetection | [Locale Detection Object](#localeDetectionObject) | How locale is determined. |
+| rtlSupport | [RTL Support Object](#rtlSupportObject) | Right-to-left layout support. |
+
+#### I18n Platform Support Object Example
+
+```yaml
+platformSupport:
+ enabled: true
+ availableLocales:
+ - en
+ - en-US
+ - en-GB
+ - es
+ - es-MX
+ - fr
+ - fr-CA
+ - de
+ - ja
+ - zh-CN
+ - zh-TW
+ - pt-BR
+ - ar
+ - he
+ localeDetection:
+ method: automatic
+ sources:
+ - userPreference
+ - accountSetting
+ - browserLocale
+ rtlSupport:
+ enabled: true
+ languages:
+ - ar
+ - he
+ - fa
+```
+
+### Locale Detection Object
+
+How locale is determined.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| method | `string` | Detection method. Values MUST be one of: `automatic`, `manual`, `both`. |
+| sources | [`string`] | Sources for locale detection (e.g., `userPreference`, `browserLocale`, `accountSetting`). |
+
+#### Locale Detection Object Example
+
+```yaml
+localeDetection:
+ method: automatic
+ sources:
+ - userPreference
+ - accountSetting
+ - browserLocale
+```
+
+### RTL Support Object
+
+Right-to-left layout support.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| enabled | `boolean` | Whether RTL is supported. Default: `false`. |
+| languages | [`string`] | RTL languages supported (e.g., `ar`, `he`, `fa`). |
+
+#### RTL Support Object Example
+
+```yaml
+rtlSupport:
+ enabled: true
+ languages:
+ - ar # Arabic
+ - he # Hebrew
+ - fa # Farsi/Persian
+ - ur # Urdu
+```
+
+### Component Translations Object
+
+Whether platform-provided components are translated.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| provided | `boolean` | Whether platform translates built-in component labels. |
+| scope | `string` | Translation scope. Values MUST be one of: `all`, `partial`, `none`. |
+
+#### Component Translations Object Example
+
+```yaml
+componentTranslations:
+ provided: true
+ scope: all
+```
+
+### I18n Developer Requirements Object
+
+What developers must handle for internationalization.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| translationMechanism | [Translation Mechanism Object](#translationMechanismObject) | How developers provide translations. |
+| marketplaceRequirement | [Marketplace I18n Requirement Object](#marketplaceI18nRequirementObject) | Localization requirements for marketplace. |
+| formatting | [Formatting Object](#formattingObject) | Who handles locale-aware formatting. |
+
+#### I18n Developer Requirements Object Example
+
+```yaml
+developerRequirements:
+ translationMechanism:
+ format: icu
+ bundleLocation: embedded
+ marketplaceRequirement:
+ required: true
+ minimumLocales:
+ - en
+ - es
+ - fr
+ - de
+ - ja
+ formatting:
+ dates: platform
+ numbers: platform
+ currencies: developer
+```
+
+### Translation Mechanism Object
+
+How developers provide translations.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| format | `string` | Translation format. Values MUST be one of: `icu`, `i18next`, `gettext`, `json`, `custom`. |
+| bundleLocation | `string` | Where bundles are stored. Values MUST be one of: `embedded`, `remote`, `platform-hosted`. |
+
+#### Translation Mechanism Object Example
+
+```yaml
+translationMechanism:
+ format: icu
+ bundleLocation: embedded
+```
+
+### Marketplace I18n Requirement Object
+
+Localization requirements for marketplace apps.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| required | `boolean` | Whether localization is required for marketplace. |
+| minimumLocales | [`string`] | Minimum required locales for marketplace (BCP 47 tags). |
+
+#### Marketplace I18n Requirement Object Example
+
+```yaml
+marketplaceRequirement:
+ required: true
+ minimumLocales:
+ - en
+ - es
+ - fr
+ - de
+ - ja
+```
+
+### Formatting Object
+
+Who handles locale-aware formatting.
+
+#### Fixed Fields
+
+| Field Name | Type | Description |
+|---|---|---|
+| dates | `string` | Who formats dates. Values MUST be one of: `platform`, `developer`. |
+| numbers | `string` | Who formats numbers. Values MUST be one of: `platform`, `developer`. |
+| currencies | `string` | Who formats currencies. Values MUST be one of: `platform`, `developer`. |
+
+#### Formatting Object Example
+
+```yaml
+formatting:
+ dates: platform
+ numbers: platform
+ currencies: developer
+```
+
+## Specification Extensions
+
+While the Fenestra I18n Extension tries to accommodate most use cases, additional data can be added to extend the specification at certain points.
+
+The extensions properties are implemented as patterned fields that are always prefixed by `x-`.
+
+| Field Pattern | Type | Description |
+|---|---|---|
+| ^x- | Any | Allows extensions to the Fenestra I18n Extension Schema. The field name MUST begin with `x-`, for example, `x-translation-service`. Field names beginning with `x-oai-` and `x-oas-` are reserved for uses defined by the [OpenAPI Initiative](https://www.openapis.org/). The value can be any valid JSON value (`null`, a primitive, an array, or an object). |
+
+The extensions may or may not be supported by the available tooling, but those may be extended as well to add requested support (if tools are internal or open-source).
+
+### Extension Example
+
+```yaml
+i18n:
+ platformSupport:
+ enabled: true
+ availableLocales: [en, es, fr]
+ x-locale-fallback-chain:
+ es-MX: [es-MX, es, en]
+ pt-BR: [pt-BR, pt, en]
+ developerRequirements:
+ translationMechanism:
+ format: icu
+ x-translation-service: https://translate.example.com
+ x-recommended-libraries:
+ - react-intl
+ - formatjs
+```
+
+## Appendix A: Complete Example
+
+This example demonstrates a comprehensive i18n configuration for a global platform:
+
+```yaml
+i18n:
+ platformSupport:
+ enabled: true
+ availableLocales:
+ - en
+ - en-US
+ - en-GB
+ - es
+ - es-MX
+ - es-ES
+ - fr
+ - fr-FR
+ - fr-CA
+ - de
+ - de-DE
+ - ja
+ - ja-JP
+ - zh-CN
+ - zh-TW
+ - pt-BR
+ - ar
+ - ar-SA
+ - he
+ - ko
+ localeDetection:
+ method: automatic
+ sources:
+ - userPreference
+ - accountSetting
+ - browserLocale
+ rtlSupport:
+ enabled: true
+ languages:
+ - ar
+ - he
+ - fa
+ componentTranslations:
+ provided: true
+ scope: all
+ developerRequirements:
+ translationMechanism:
+ format: icu
+ bundleLocation: embedded
+ marketplaceRequirement:
+ required: true
+ minimumLocales:
+ - en
+ - es
+ - fr
+ - de
+ - ja
+ formatting:
+ dates: platform
+ numbers: platform
+ currencies: developer
+ documentation: https://developers.example.com/docs/internationalization
+```
+
+## Appendix B: Revision History
+
+| Version | Date | Notes |
+|---------|------|-------|
+| 0.1.0 | 2024-12-27 | Initial release of I18n Extension extracted from Fenestra Core 0.1.0 |