Guide
Storing Plugin Activation State
What to store after activation, what never to store, and how local cache affects startup validation and offline grace.
SoundSync
Cache fields
Use the canonical fields returned by activation/validation and separate test/live records.
| Field | Use | Rule |
|---|---|---|
| license_key | Required for serial flows | Sensitive. Encrypt/redact. Delete on deactivation. |
| instance_id | Required | Machine identity. Must match current machine. |
| token | Optional but used for validation fast path | Sensitive validation token. Rotate when server returns a new value. |
| status | Required | Only activated/valid states may unlock. |
| activationId | Optional | Useful validation identity. Delete on deactivation. |
| licenseReference | Optional | Useful validation identity. Delete on deactivation. |
| productId | Required | Must match current product config. |
| graceExpiresAt | Optional | Offline grace deadline from last successful activation/validation. |
| offlineGraceDays | Optional | Display/diagnostic value. Do not use to reset grace locally. |
| subscription_* fields | Optional | Display/status values. Explicit inactive/payment-required states lock. |
SoundSync
Sanitized activation record
This is an example shape; use encrypted platform storage and atomic writes rather than a plain JSON file.
JSON
{
"schemaVersion": 1,
"environment": "test",
"productId": "prod_demo_piano",
"appId": "ss_prod_demoapp123",
"license_key": "DEMO-SERIAL-0001",
"instance_id": "machine-demo-001",
"status": "activated",
"activationId": "act_demo_123",
"licenseReference": "lic_demo_123",
"token": "validation-token-from-activation",
"graceExpiresAt": "2026-08-23T15:00:00.000Z",
"offlineGraceDays": 30,
"lastValidatedAt": "2026-07-24T15:00:00.000Z"
}
SoundSync
Storage requirements
Local storage is part of the security boundary.
| Area | Requirement |
|---|---|
| Encryption | Use platform secure storage where possible. At minimum encrypt sensitive fields at rest. |
| Atomic writes | Write to a temp record and replace atomically to avoid corrupting the last valid cache. |
| Corruption | Treat corrupt or schema-invalid cache as locked; do not unlock from partial JSON. |
| Separation | Separate by productId, appId, environment, customer/account where applicable, and machine identity. |
| Deactivation cleanup | Delete activation state and grace fields after successful deactivation. |
| Pending claim persistence | Store claim_id, license_key, instance_id, email, productId, and started time only while the flow is pending. |
| Never store | Customer passwords, plugin secrets outside generated config, or plugin key/secret in logs. |
