003 Extensible Platform Schemas
Date: 2026-05-30
Status: Superseded by
ADR 017
Deciders: Jennifer Power
Context#
The initial design hardcoded support for five platforms (kubernetes, terraform, docker, ansible, ci). This is too restrictive - users may need to generate policies for custom platforms or infrastructure not covered by the built-ins.
Decision#
Support both built-in platforms and user-provided custom platforms via configuration.
Built-in schemas are embedded in the binary. Users can extend with custom schemas via complypack.yaml:
platform: custom-platform
gemara-catalogs:
- oci://ghcr.io/complytime/controls-catalog:v1
platform-schemas:
custom-platform: ./schemas/custom.cue
special-infra: https://example.com/schemas/platform.cueRationale#
Why Extensibility?#
- Unpredictable platform needs: Can’t predict every platform users will target
- Custom infrastructure: Organizations have custom platforms we can’t know about
- Rapid platform evolution: New infrastructure tools emerge constantly
- Override capability: Users may want to customize built-in schemas
Why Configuration-based Extension?#
- Explicit and clear: User declares exactly what schemas are available
- Version control friendly:
complypack.yamllives in the repo - Supports local and remote: Can use local files or fetch from URLs
- No directory scanning: Explicit is better than implicit discovery
Considered Alternatives#
Hardcoded platforms only:
- ❌ Too restrictive
- ❌ Requires complypack updates for new platforms
- ✅ Simpler implementation
- ✅ Fewer edge cases
Auto-discovery from directory:
.complypack/schemas/
custom-platform.cue
another-platform.cue- ❌ Implicit behavior (magic directory)
- ❌ Harder to debug (“why isn’t my schema loading?”)
- ✅ No configuration needed
- ✅ Just drop files and go
Plugin system:
- ❌ Over-engineered for this need
- ❌ Adds significant complexity
- ✅ Most flexible approach
Design#
Schema Loading Priority#
- Load all built-in schemas (from embedded files)
- Load user-provided schemas (from
platform-schemasconfig) - Merge: user schemas override built-ins if names conflict
- Validate that
platformexists in merged set
User Schema Sources#
Local CUE files:
platform-schemas:
custom: ./schemas/custom.cue- Relative to
complypack.yamllocation - Converted from CUE → JSON Schema at MCP startup
Remote URLs:
platform-schemas:
shared: https://example.com/schemas/platform.cue- Fetched at MCP startup
- Cached (TBD: cache location and invalidation)
Override Behavior#
If user provides a schema with same name as built-in:
platform-schemas:
kubernetes: ./schemas/custom-k8s.cue- User’s
custom-k8s.cuereplaces the built-inkubernetesschema - Logged: “Using custom schema for platform ‘kubernetes’”
Trade-offs Accepted#
- Startup latency: Fetching remote schemas adds delay
- Network dependency: Remote schemas require network access
- CUE runtime dependency: Need CUE Go API to convert user schemas
- More error cases: Invalid CUE, unreachable URLs, parse failures
Error Handling#
| Error | Behavior |
|---|---|
| User schema file not found | Refuse to start: “Schema file ‘./schemas/custom.cue’ not found” |
| User schema invalid CUE | Refuse to start: “Failed to parse schema ‘custom’: |
| User schema remote fetch failure | Refuse to start: “Failed to fetch schema from https://…: |
| User schema overrides built-in | Log warning: “Custom schema overrides built-in platform ‘kubernetes’” |
Fail-fast: Server refuses to start with invalid/unreachable user schemas.
Consequences#
Positive#
- Users can support any platform
- Organizations can share schemas via URLs
- Built-in schemas provide good defaults
- Override mechanism allows customization
Negative#
- More complex schema loading logic
- CUE Go API required at runtime (for user schemas)
- Network dependency for remote schemas
- More error cases to handle
Implementation#
- Extend
complypack.yamlschema to includeplatform-schemasmap - Implement schema loading:
- Load built-ins from
embed.FS - Load user CUE from local files
- Fetch user CUE from URLs
- Convert all CUE → JSON Schema
- Merge (user overrides built-ins)
- Load built-ins from
- Update
ListResourcesto include all (built-in + user) schemas - Update
ReadResourceto serve from merged map - Update error messages to list available platforms
Future Considerations#
- Schema caching: Cache remote schemas locally with TTL
- Schema validation: Validate user schemas against a meta-schema
- Schema registry: Central registry of community-contributed schemas
- Hot reload: Reload schemas without restarting MCP server