Container Manifest and Policy Configuration
Overview
A Locktera container manifest defines the access policy, DRM rules, and file metadata for a container at creation time.
The manifest is provided when encoding a container and is used to enforce:
-
Who can decrypt the container (
recipients) -
What they can do (
downloadable,hidden, view/download mappings) -
Additional access controls (password, time window, geo/IP limits, open limits)
-
How policies behave over time (
drm.dynamic)
When to Use a Manifest
Use a manifest when you need to:
-
Restrict access to specific recipients or domains
-
Enforce time-limited access windows
-
Block access by IP or geolocation
-
Limit how many times a container can be opened
-
Require a password to decrypt
-
Hide or remap files in the viewer menu
-
Provide page counts or duration metadata for richer viewing behavior
If you do not need custom policies, you can use a minimal manifest with only downloadable.
Manifest Schema
Top-Level Manifest
type Manifest = {
container: ContainerInfo;
files?: Record<string, FileInfo>;
};,
-
container(required) — container-wide policy configuration -
files(optional) — per-file metadata keyed by filename
Container Policy
container.recipients
A list of email addresses allowed to decrypt the container. Supports wildcard patterns.
Supported formats:
-
example@gmail.com— single address -
*@locktera.com— any email from a domain -
*@*— any logged-in viewer (all authenticated users)
Example:
{
"container": {
"recipients": ["*@locktera.com"],
"downloadable": false
}
}
If recipients is omitted, access is determined by the container’s default access model (for example: owner-only or policy-defined recipients, depending on your deployment).
container.downloadable (required)
Controls whether recipients may download the container contents.
-
true— downloads allowed for viewers -
false— downloads disabled for viewers
Note: The sender/owner can always retrieve content through authorized tooling.
Example:
{
"container": {
"downloadable": true
}
}
container.password (optional)
If provided, viewers must supply this password to decrypt the container contents.
Example:
{
"container": {
"recipients": ["alice@company.com"],
"downloadable": false,
"password": "CorrectHorseBatteryStaple"
}
}
container.drm (optional)
Defines additional access control rules that are evaluated at decryption time.
DRM Policy
drm.dynamic (optional)
Controls whether DRM rules are modifiable after encoding.
-
false(default): DRM is encrypted into the container and cannot be changed -
true: DRM is stored in the Locktera database and can be updated by API
Use cases:
-
dynamic: false— strongest immutability; fixed policy -
dynamic: true— enterprise controls; supports updates like revocation, time changes, new recipients, etc.
Example:
{
"container": {
"downloadable": false,
"drm": {
"dynamic": true
}
}
}
drm.time (optional)
Time window during which access is permitted.
-
start— before this time, decryption is denied -
end— after this time, decryption is denied
Example:
{
"container": {
"recipients": ["vendor@company.com"],
"downloadable": false,
"drm": {
"dynamic": true,
"time": {
"start": "2026-02-21T00:00:00Z",
"end": "2026-03-21T00:00:00Z"
}
}
}
}
Guideline: Use ISO-8601 timestamps in UTC (e.g., ...Z) for consistency.
drm.opens (optional)
Limits how many times each recipient can open the container.
Example:
{
"container": {
"recipients": ["auditor@company.com"],
"downloadable": false,
"drm": {
"opens": 3
}
}
}
drm.ip (optional)
IP-based allow/block rules. Supported formats:
-
192.168.1.10(single IP) -
192.168.1.0/24(CIDR subnet) -
192.*.1.*(wildcard) -
192.168.1.0-192.168.1.255(range) -
192.168.1.10/255.0.255.0(mask)
Example: allow only corporate subnet
{
"container": {
"recipients": ["*@company.com"],
"downloadable": false,
"drm": {
"ip": {
"allow": ["203.0.113.0/24"]
}
}
}
}
Example: block a specific address
{
"container": {
"downloadable": false,
"drm": {
"ip": {
"block": ["198.51.100.10"]
}
}
}
}
Rule behavior:
-
If any
allowrules exist → only allow viewers who match an allow rule -
If only
blockrules exist → allow viewers unless they match a block rule
drm.geo (optional)
Geolocation-based allow/block rules using:
-
continent -
country -
subdivision(state/province) -
city
Example: allow US only
{
"container": {
"downloadable": false,
"drm": {
"geo": {
"allow": [
{ "country": "United States" }
]
}
}
}
}
Example: block a country
{
"container": {
"downloadable": false,
"drm": {
"geo": {
"block": [
{ "country": "Russia" }
]
}
}
}
}
File Metadata
Per-file metadata is defined under files, keyed by filename.
files?: Record<string, FileInfo>;
FileInfo fields
-
type— MIME type (e.g.,application/pdf,video/mp4) -
pages— document page count -
duration— media duration in seconds -
hidden— hides file from viewer menu (defaultfalse) -
view_instead— show a different file when selected -
download_instead— download a different file when the download button is pressed
Example:
{
"container": {
"downloadable": true
},
"files": {
"report.pdf": {
"type": "application/pdf",
"pages": 42
},
"raw-footage.mov": {
"type": "video/quicktime",
"duration": 1840,
"hidden": true,
"view_instead": "preview.mp4"
},
"preview.mp4": {
"type": "video/mp4",
"duration": 120,
"download_instead": "raw-footage.mov"
}
}
}
Guideline: Use file remapping (view_instead, download_instead) to provide secure previews while keeping high-value originals hidden or restricted.
Manifest Quick Reference
Top-Level
|
Field |
Type |
Required |
Purpose |
|---|---|---|---|
|
|
|
✅ |
Container-wide policy and DRM configuration |
|
|
|
❌ |
Per-file metadata, keyed by filename |
container (ContainerInfo)
|
Field |
Type |
Required |
Purpose |
Example |
|---|---|---|---|---|
|
|
|
❌ |
Who is allowed to decrypt (supports wildcards) |
|
|
|
|
✅ |
Whether viewers can download content |
|
|
|
|
❌ |
Password required for viewers to decrypt |
|
|
|
|
❌ |
Additional decryption-time rules |
|
recipients address
-
example@gmail.com— exact address -
*@locktera.com— any user from a domain -
*@*— any authenticated viewer
container.drm (Drm)
|
Field |
Type |
Required |
Purpose |
Example |
|---|---|---|---|---|
|
|
|
❌ |
Whether DRM can be updated after encode |
|
|
|
|
❌ |
Allow/block by geolocation |
|
|
|
|
❌ |
Allow/block by IP patterns |
|
|
|
|
❌ |
Max opens per viewer |
|
|
|
|
❌ |
Access window (start/end) |
|
DRM Rules (DrmRules<T>)
|
Field |
Type |
Purpose |
|---|---|---|
|
|
|
If present, only viewers matching an allow rule are permitted |
|
|
|
Viewers matching a block rule are denied |
Evaluation rule
-
If any
allowrules exist → only allow matches toallow -
Else if only
blockrules exist → deny matches toblock, allow all others
geo rules (GeoRule)
|
Field |
Type |
Purpose |
Example |
|---|---|---|---|
|
|
|
Restrict by continent |
|
|
|
|
Restrict by country |
|
|
|
|
Restrict by state/province |
|
|
|
|
Restrict by city |
|
time rule (TimeRule)
|
Field |
Type |
Purpose |
Example |
|---|---|---|---|
|
|
|
Before this time, deny decryption |
|
|
|
|
After this time, deny decryption |
|
Guideline: represent timestamps as ISO-8601 UTC strings (...Z) in API requests.
files metadata (FileInfo)
|
Field |
Type |
Purpose |
Example |
|---|---|---|---|
|
|
|
MIME type |
|
|
|
|
Document page count |
|
|
|
|
Media duration (seconds) |
|
|
|
|
Hide from viewer menu |
|
|
|
|
Display another file when selected |
|
|
|
|
Download another file instead |
|
Manifest Validation Rules
Required fields
container
-
containermust be present.
container.downloadable
-
container.downloadablemust be present and must be a boolean (trueorfalse).
Recipient validation
container.recipients
If provided:
-
Must be a non-empty array of strings.
-
Each string must be one of:
-
exact email:
user@example.com -
domain wildcard:
*@example.com -
universal authenticated wildcard:
*@*
-
Invalid examples
-
"@company.com"(missing local part wildcard) -
"*company.com"(missing@) -
"*@company"(not a valid domain format)
Behavior
-
If
recipientsis omitted, access defaults to your platform’s baseline policy (often owner-only unless expanded via DRM/API).
Password validation
container.passord
If provided:
-
Must be a non-empty string.
-
Recommended minimum length: 12+ characters
-
Should not be included in logs or error messages.
-
If password is set, viewers must supply it to decrypt.
DRM validation
container.drm.dynamic
If provided:
-
Must be boolean.
-
Default is
false.
Behavior
-
dynamic: false→ DRM rules are embedded and cannot be updated via API. -
dynamic: true→ DRM can be modified via DRM endpoints (policy updates without changing container contents).
Time rule validation
drm.time.start and drm.time.end
If provided:
-
Must be valid ISO-8601 timestamps (recommended) or valid
Datevalues depending on implementation. -
If both are present:
-
startmust be earlier thanend.
-
Recommended runtime behavior
-
Now <
start→ deny withaccess_not_yet_valid -
Now >
end→ deny withaccess_expired
Opens validation
drm.opens
If provided:
-
Must be an integer.
-
Must be >= 1.
-
Recommended max (optional): set a practical ceiling (e.g., 1000) to avoid abuse.
IP rule validation
drm.ip.allow / drm.ip.block
If provided:
-
Must be an array of strings.
-
Each string must match one supported IP format:
-
192.168.1.10(single IP) -
192.168.1.0/24(CIDR) -
192.*.1.*(wildcard) -
192.168.1.0-192.168.1.255(range) -
192.168.1.10/255.0.255.0(mask)
-
Evaluation
-
If any
allowexists → only allow matches to allow rules. -
If only
blockexists → deny matches to block rules.
Geo rule validation
drm.geo.allow / drm.geo.block
If provided:
-
Must be an array of GeoRule objects.
-
Each GeoRule may include any of:
-
continent,country,subdivision,city
-
-
A GeoRule with no fields set should be rejected.
Recommended matching behavior
-
A viewer matches a GeoRule if all specified fields match their resolved location.
File metadata validation
files object
If provided:
-
Must be an object keyed by filename.
-
Each key should correspond to a file included during encode (recommended strict behavior).
FileInfo.view_instead / download_instead
If provided:
-
Must reference a filename that exists in the container.
-
Prevent self-reference loops:
-
view_insteadshould not equal the same filename -
chained references should not create cycles (recommended)
-
pages and duration
If provided:
-
Must be numbers.
-
pagesmust be >= 1 -
durationmust be >= 0
Common Manifest Examples
1) Minimal manifest (downloads allowed)
{
"container": {
"downloadable": true
}
}
2) Domain-restricted sharing + no downloads
{
"container": {
"recipients": ["*@company.com"],
"downloadable": false
}
}
3) Time-limited vendor access + IP allowlist
{
"container": {
"recipients": ["vendor@partner.com"],
"downloadable": false,
"drm": {
"dynamic": true,
"time": {
"start": "2026-02-21T00:00:00Z",
"end": "2026-03-01T00:00:00Z"
},
"ip": {
"allow": ["203.0.113.0/24"]
}
}
}
}
4) Fixed (non-modifiable) policy
{
"container": {
"recipients": ["auditor@agency.gov"],
"downloadable": false,
"drm": {
"dynamic": false,
"opens": 1
}
}
}
Security Notes
-
Container contents remain immutable after encoding.
-
Access is evaluated at decryption time, not at download time.
-
If
drm.dynamicis enabled, policies may be updated through the DRM endpoint without modifying container contents. -
Audit logs are generated for access attempts (authorized and denied), enabling compliance and forensic review.
