Description
A sandbox with custom policy presets applied via policy --from-file / --from-dir loses them after snapshot restore (including snapshot restore --to <dst>). The restored sandbox keeps its built-in presets but none of the custom ones.
Root cause
snapshot create records applied policy presets into the rebuild manifest so they can be re-applied after destroy/recreate, because presets live in the gateway policy engine rather than on the sandbox filesystem. But it only captures the built-in preset names (policyPresets, from registry.policies):
- The
RebuildManifest interface has policyPresets?: string[] but no field for custom presets.
createBackup captures sb.policies only.
snapshot restore reconciles policyPresets only.
Custom presets are tracked separately in registry.customPolicies (each CustomPolicyEntry carries the preset's full content), and they live in the same gateway-only location, so they are subject to the exact same loss on restore — but nothing captures or replays them. Result: custom policies are silently dropped.
Expected
snapshot restore re-applies custom policy presets just like built-in presets, so the restored sandbox's effective policy matches the snapshot.
Fix
Since CustomPolicyEntry.content is self-contained, capture customPolicies into the rebuild manifest and reconcile them on restore (re-apply by content via the existing custom-preset apply path, which also re-records them in the registry; remove any the snapshot did not record), mirroring how policyPresets are reconciled.
Description
A sandbox with custom policy presets applied via
policy --from-file/--from-dirloses them aftersnapshot restore(includingsnapshot restore --to <dst>). The restored sandbox keeps its built-in presets but none of the custom ones.Root cause
snapshot createrecords applied policy presets into the rebuild manifest so they can be re-applied after destroy/recreate, because presets live in the gateway policy engine rather than on the sandbox filesystem. But it only captures the built-in preset names (policyPresets, fromregistry.policies):RebuildManifestinterface haspolicyPresets?: string[]but no field for custom presets.createBackupcapturessb.policiesonly.snapshot restorereconcilespolicyPresetsonly.Custom presets are tracked separately in
registry.customPolicies(eachCustomPolicyEntrycarries the preset's fullcontent), and they live in the same gateway-only location, so they are subject to the exact same loss on restore — but nothing captures or replays them. Result: custom policies are silently dropped.Expected
snapshot restorere-applies custom policy presets just like built-in presets, so the restored sandbox's effective policy matches the snapshot.Fix
Since
CustomPolicyEntry.contentis self-contained, capturecustomPoliciesinto the rebuild manifest and reconcile them on restore (re-apply by content via the existing custom-preset apply path, which also re-records them in the registry; remove any the snapshot did not record), mirroring howpolicyPresetsare reconciled.