BEGIN; ALTER TABLE device ADD COLUMN activation_state varchar(24), ADD COLUMN activation_revision bigint NOT NULL DEFAULT 1, ADD COLUMN activation_reason text, ADD COLUMN activation_updated_at timestamptz NOT NULL DEFAULT now(); UPDATE device d SET activation_state = CASE WHEN d.status = 'revoked' THEN 'REVOKED' WHEN EXISTS (SELECT 1 FROM device_binding b WHERE b.device_id=d.id AND b.unbound_at IS NULL) AND EXISTS (SELECT 1 FROM device_credential dc WHERE dc.device_id=d.id AND dc.status='active') AND ( COALESCE((SELECT dt.desired_config->>'voice_runtime' FROM device_twin dt WHERE dt.device_id=d.id),'legacy_voicechat') <> 'volc_hardware_agent' OR EXISTS ( SELECT 1 FROM hardware_agent_provider_credential pc WHERE pc.device_id=d.id AND pc.status='ACTIVE' ) ) THEN 'ACTIVE' WHEN EXISTS ( SELECT 1 FROM device_binding b WHERE b.device_id=d.id AND b.unbound_at IS NULL ) THEN 'BOUND' ELSE 'CLAIMABLE' END, activation_reason = 'migration-50-backfill'; ALTER TABLE device ALTER COLUMN activation_state SET NOT NULL, ALTER COLUMN activation_state SET DEFAULT 'FACTORY', ADD CONSTRAINT device_activation_state_check CHECK (activation_state IN ('FACTORY','CLAIMABLE','BOUND','PROVISIONING','ACTIVE','LOST','REVOKED')); CREATE INDEX device_tenant_activation_state_idx ON device(tenant_id,activation_state,activation_updated_at DESC); CREATE TABLE device_activation_transition ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), public_id uuid NOT NULL UNIQUE DEFAULT gen_random_uuid(), tenant_id uuid NOT NULL REFERENCES tenant(id), device_id uuid NOT NULL REFERENCES device(id), from_state varchar(24), to_state varchar(24) NOT NULL, reason text NOT NULL, source varchar(80) NOT NULL, actor_type varchar(40) NOT NULL, actor_public_id uuid, request_id varchar(160), activation_revision bigint NOT NULL, created_at timestamptz NOT NULL DEFAULT now(), CONSTRAINT device_activation_transition_from_check CHECK ( from_state IS NULL OR from_state IN ('FACTORY','CLAIMABLE','BOUND','PROVISIONING','ACTIVE','LOST','REVOKED') ), CONSTRAINT device_activation_transition_to_check CHECK ( to_state IN ('FACTORY','CLAIMABLE','BOUND','PROVISIONING','ACTIVE','LOST','REVOKED') ), UNIQUE(device_id,activation_revision) ); CREATE INDEX device_activation_transition_tenant_device_idx ON device_activation_transition(tenant_id,device_id,created_at DESC); INSERT INTO device_activation_transition( tenant_id,device_id,from_state,to_state,reason,source,actor_type,activation_revision ) SELECT tenant_id,id,NULL,activation_state,'migration-50-backfill','migration','system',activation_revision FROM device; ALTER TABLE hardware_agent_provider_credential DROP CONSTRAINT hardware_agent_provider_credential_status_check; ALTER TABLE hardware_agent_provider_credential ADD CONSTRAINT hardware_agent_provider_credential_status_check CHECK (status IN ('ACTIVE','SUSPENDED','REVOKED')); COMMIT;