{ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "snapshot.schema.json", "title": "Tibi snapshot config", "description": "Configuration for automated point-in-time snapshots of project collections and media.", "type": "object", "additionalProperties": false, "patternProperties": { "^x-": {} }, "properties": { "name": { "type": "string", "description": "Unique identifier for this snapshot profile (e.g. 'content-navigation')" }, "description": { "type": "string", "description": "Optional human-readable explanation of this snapshot profile" }, "collections": { "type": "array", "description": "Collection filter: empty = all, include-mode = only listed, exclude-mode = all except listed. Mixed include+exclude is invalid.", "items": { "oneOf": [ { "type": "string", "description": "Shorthand for {name: '...', mode: 'include'}" }, { "type": "object", "additionalProperties": false, "properties": { "name": { "type": "string" }, "mode": { "type": "string", "enum": ["include", "exclude"], "description": "'include' = only this collection, 'exclude' = all except this collection. Default 'include' when omitted." } }, "required": ["name"] } ] } }, "includeMedia": { "type": "boolean", "description": "Whether to include media files (file/file[] fields) via hardlinks. Default: true.", "default": true }, "collectionDedup": { "type": "boolean", "description": "Enable SHA256-based deduplication of collection JSON exports. Identical exports share one canonical copy via hardlinks in .store/collections/. Default: false.", "default": false }, "mode": { "type": "string", "enum": ["json", "db", "both"], "description": "Storage strategy for collection data. 'json' = BSON Extended JSON files on disk (current, implemented), 'db' = MongoDB $out copy (future), 'both' = both (future). Default: 'json'." }, "retention": { "type": "object", "description": "Auto-pruning rules for old snapshot entries. Omit for unlimited retention.", "additionalProperties": false, "properties": { "maxCount": { "type": "integer", "minimum": 1, "description": "Maximum number of snapshot entries to keep. Oldest entries are pruned first." }, "maxAge": { "type": "string", "description": "Maximum age of snapshot entries (e.g. '720h' = 30 days, '7d' = 7 days, '168h'). Entries older than this are pruned." }, "maxSizeBytes": { "type": "integer", "minimum": 1, "description": "Maximum total size of snapshot entries in bytes. Oldest entries are pruned first until under this limit." } } }, "schedule": { "type": "string", "description": "Cron expression for automatic execution (e.g. '0 3 * * *' = daily 3am UTC, '@every 24h'). Empty = manual trigger only." }, "permissions": { "type": "array", "description": "Bare permission names for team-based access (Phase 2). Empty = admin-only in Phase 1.", "items": { "type": "string" } }, "enabled": { "type": "boolean", "description": "Whether this snapshot profile is active. Disabled profiles are skipped by the scheduler but can still be triggered manually.", "default": false } }, "required": ["name"] }