BEGIN; CREATE TABLE hardware_agent_license ( 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), provider varchar(40) NOT NULL DEFAULT 'volcengine', instance_id varchar(200) NOT NULL, product_key varchar(200) NOT NULL, license_ref varchar(200) NOT NULL UNIQUE, payload_digest varchar(64) NOT NULL CHECK (payload_digest ~ '^[0-9a-f]{64}$'), encrypted_payload bytea NOT NULL, nonce bytea NOT NULL, status varchar(24) NOT NULL DEFAULT 'AVAILABLE' CHECK (status IN ('AVAILABLE','ALLOCATED','ACTIVE','SUSPENDED','EXPIRED','REVOKED')), allocated_device_id uuid, allocated_at timestamptz, activated_at timestamptz, expires_at timestamptz NOT NULL, released_at timestamptz, revoked_at timestamptz, last_error_code varchar(100), created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), version bigint NOT NULL DEFAULT 1 CHECK (version > 0), CONSTRAINT hardware_agent_license_device_tenant_fk FOREIGN KEY (allocated_device_id, tenant_id) REFERENCES device(id,tenant_id), CONSTRAINT hardware_agent_license_assignment_check CHECK ( (status='AVAILABLE' AND allocated_device_id IS NULL) OR (status IN ('ALLOCATED','ACTIVE','SUSPENDED') AND allocated_device_id IS NOT NULL) OR status IN ('EXPIRED','REVOKED') ) ); CREATE UNIQUE INDEX hardware_agent_license_device_active_key ON hardware_agent_license(allocated_device_id) WHERE status IN ('ALLOCATED','ACTIVE','SUSPENDED'); CREATE INDEX hardware_agent_license_pool_idx ON hardware_agent_license(tenant_id,provider,instance_id,product_key,status,expires_at); CREATE FUNCTION enforce_hardware_license_device_state() RETURNS trigger LANGUAGE plpgsql AS $$ DECLARE changed_revision bigint; BEGIN IF NEW.allocated_device_id IS NOT NULL AND NEW.status IN ('SUSPENDED','EXPIRED','REVOKED') AND OLD.status IS DISTINCT FROM NEW.status THEN UPDATE device SET activation_state='PROVISIONING',activation_revision=activation_revision+1, activation_reason='license-' || lower(NEW.status),activation_updated_at=now(),version=version+1,updated_at=now() WHERE id=NEW.allocated_device_id AND tenant_id=NEW.tenant_id AND activation_state='ACTIVE' RETURNING activation_revision INTO changed_revision; IF changed_revision IS NOT NULL THEN INSERT INTO device_activation_transition( tenant_id,device_id,from_state,to_state,reason,source,actor_type,activation_revision ) VALUES( NEW.tenant_id,NEW.allocated_device_id,'ACTIVE','PROVISIONING', '硬件智能体License状态变为' || NEW.status,'license-state-trigger','system',changed_revision ); END IF; END IF; RETURN NEW; END; $$; CREATE TRIGGER hardware_agent_license_device_state_trigger AFTER UPDATE OF status ON hardware_agent_license FOR EACH ROW EXECUTE FUNCTION enforce_hardware_license_device_state(); WITH transitioned AS ( UPDATE device d SET activation_state='PROVISIONING',activation_revision=activation_revision+1, activation_reason='license-required-v51',activation_updated_at=now(),version=version+1,updated_at=now() FROM device_twin dt WHERE dt.device_id=d.id AND d.status='registered' AND d.activation_state='ACTIVE' AND COALESCE(dt.desired_config->>'voice_runtime','legacy_voicechat')='volc_hardware_agent' RETURNING d.tenant_id,d.id,d.activation_revision ) INSERT INTO device_activation_transition( tenant_id,device_id,from_state,to_state,reason,source,actor_type,activation_revision ) SELECT tenant_id,id,'ACTIVE','PROVISIONING','硬件智能体必须分配并确认有效License','migration-51','system',activation_revision FROM transitioned; COMMIT;