Learn how CE.SDK’s rules system enforces design constraints and controls editing permissions through the scopes mechanism.
In CE.SDK, rules are the design constraints and guardrails that control which editing operations are permitted. The primary mechanism for enforcing rules is the scopes system — permission flags that let you build guided editing experiences, maintain brand consistency, ensure design quality, and prevent unauthorized modifications.
This guide covers the scopes system conceptually: the available scope categories, the difference between global and block-level scopes, and how to resolve the effective permission for any block. For detailed implementation of specific rule use cases, see the guides linked under Common Use Cases.
What Are Scopes#
Scopes are permission flags that control specific editing capabilities. Each scope maps to a particular operation category, identified by a string key such as layer/move or fill/change. CE.SDK organizes scopes into four categories:
Layer operations — Control positioning and transformation:
layer/move,layer/resize,layer/rotate,layer/fliplayer/crop,layer/opacity,layer/blendModelayer/visibility,layer/clipping
Appearance — Control visual effects and adjustments:
appearance/adjustments,appearance/filter,appearance/effectappearance/blur,appearance/shadow,appearance/animation
Content editing — Control content modifications:
text/edit,text/characterfill/change,fill/changeTypestroke/change,shape/change
Lifecycle — Control block management:
lifecycle/destroy,lifecycle/duplicateeditor/add,editor/select
Setting Global Scopes#
Global scopes set editor-wide defaults that apply to every block. Use setGlobalScope(key:value:) with one of three GlobalScope permission levels:
.allow— The operation is always permitted for all blocks..deny— The operation is always blocked for all blocks..defer— Control is deferred to each block’s individual scope setting.
// The default Creator role allows every scope globally, which would short-circuit// the block-level checks below — set each scope to `.defer` to honor per-block settings.// Layer operationstry engine.editor.setGlobalScope(key: "layer/move", value: .defer)try engine.editor.setGlobalScope(key: "layer/resize", value: .defer)try engine.editor.setGlobalScope(key: "layer/rotate", value: .defer)try engine.editor.setGlobalScope(key: "layer/flip", value: .defer)try engine.editor.setGlobalScope(key: "layer/crop", value: .defer)try engine.editor.setGlobalScope(key: "layer/opacity", value: .defer)try engine.editor.setGlobalScope(key: "layer/blendMode", value: .defer)try engine.editor.setGlobalScope(key: "layer/visibility", value: .defer)try engine.editor.setGlobalScope(key: "layer/clipping", value: .defer)// Appearancetry engine.editor.setGlobalScope(key: "appearance/adjustments", value: .defer)try engine.editor.setGlobalScope(key: "appearance/filter", value: .defer)try engine.editor.setGlobalScope(key: "appearance/effect", value: .defer)try engine.editor.setGlobalScope(key: "appearance/blur", value: .defer)try engine.editor.setGlobalScope(key: "appearance/shadow", value: .defer)// Content editingtry engine.editor.setGlobalScope(key: "fill/change", value: .defer)try engine.editor.setGlobalScope(key: "fill/changeType", value: .defer)try engine.editor.setGlobalScope(key: "stroke/change", value: .defer)// Lifecycletry engine.editor.setGlobalScope(key: "lifecycle/destroy", value: .defer)try engine.editor.setGlobalScope(key: "lifecycle/duplicate", value: .defer)try engine.editor.setGlobalScope(key: "editor/add", value: .defer)try engine.editor.setGlobalScope(key: "editor/select", value: .defer)When a scope is set to .defer, the effective permission comes from the block-level setting, enabling fine-grained per-element control. Read the current value back with getGlobalScope(key:).
Setting Block-Level Scopes#
Block-level scopes override a deferred global setting for individual blocks. Use setScopeEnabled(_:key:enabled:) to enable or disable an operation on a specific block. The example creates five demo blocks and configures each with a different scope category:
layerBlock— Layer operations disabled; other categories editable.appearanceBlock— Appearance scopes disabled.contentBlock— Content-editing scopes disabled.lockedBlock— Every scope disabled, fully locking the block.enabledBlock— Every scope enabled, leaving the block fully editable.
The first block disables all layer operations while keeping the remaining categories editable:
try engine.block.setScopeEnabled(layerBlock, key: "layer/move", enabled: false)try engine.block.setScopeEnabled(layerBlock, key: "layer/resize", enabled: false)try engine.block.setScopeEnabled(layerBlock, key: "layer/rotate", enabled: false)try engine.block.setScopeEnabled(layerBlock, key: "layer/flip", enabled: false)try engine.block.setScopeEnabled(layerBlock, key: "layer/crop", enabled: false)try engine.block.setScopeEnabled(layerBlock, key: "layer/opacity", enabled: false)try engine.block.setScopeEnabled(layerBlock, key: "layer/blendMode", enabled: false)try engine.block.setScopeEnabled(layerBlock, key: "layer/visibility", enabled: false)try engine.block.setScopeEnabled(layerBlock, key: "layer/clipping", enabled: false)// Keep other categories editable.try engine.block.setScopeEnabled(layerBlock, key: "fill/change", enabled: true)try engine.block.setScopeEnabled(layerBlock, key: "lifecycle/destroy", enabled: true)try engine.block.setScopeEnabled(layerBlock, key: "editor/select", enabled: true)Block-level settings only take effect when the matching global scope is .defer. Query a block’s current setting with isScopeEnabled(_:key:).
Checking Scope Permissions#
Before performing an operation programmatically, verify that it is allowed with isAllowedByScope(_:key:). This method resolves the effective permission from both the global and block-level settings:
let canMoveLayer = try engine.block.isAllowedByScope(layerBlock, key: "layer/move")let canMoveEnabled = try engine.block.isAllowedByScope(enabledBlock, key: "layer/move")let canMoveLocked = try engine.block.isAllowedByScope(lockedBlock, key: "layer/move")
print("Layer block - can move: \(canMoveLayer)") // falseprint("Enabled block - can move: \(canMoveEnabled)") // trueprint("Locked block - can move: \(canMoveLocked)") // falseA global .deny blocks an operation on every block regardless of its block-level setting — even a fully enabled block can no longer perform the operation:
try engine.editor.setGlobalScope(key: "layer/flip", value: .deny)let canFlipEnabled = try engine.block.isAllowedByScope(enabledBlock, key: "layer/flip")
print("Enabled block - can flip after global deny: \(canFlipEnabled)") // falseCommon Use Cases#
The scopes system supports a range of rule-enforcement scenarios:
- Lock content — Prevent modifications to specific elements such as logos or legal text.
- Define safe zones — Mark areas where content must remain for correct trimming.
- Enforce brand guidelines — Restrict fonts, colors, and styles to approved options.
- Moderate content — Integrate external services to validate content appropriateness.
API Reference#
| Method | Category | Purpose |
|---|---|---|
engine.editor.setGlobalScope(key:value:) | Global | Set an editor-wide scope permission |
engine.editor.getGlobalScope(key:) | Global | Get the current global scope value |
engine.block.setScopeEnabled(_:key:enabled:) | Block | Enable or disable a scope for a specific block |
engine.block.isScopeEnabled(_:key:) | Block | Check whether a scope is enabled for a block |
engine.block.isAllowedByScope(_:key:) | Block | Check whether an operation is allowed |