err=tx.QueryRow(ctx,`SELECT public_key_base64,status FROM firmware_signing_key WHERE tenant_id=$1::uuid AND key_id=$2 FOR UPDATE`,a.tenantID,keyID).Scan(&existingPublicKey,&status)
iferrors.Is(err,pgx.ErrNoRows){
if_,err:=tx.Exec(ctx,`INSERT INTO firmware_signing_key(tenant_id,key_id,public_key_base64,created_by) VALUES($1::uuid,$2,$3,$4::uuid)`,a.tenantID,keyID,publicKeyBase64,a.userID);err!=nil{
(SELECT count(*) FROM firmware_release fr WHERE fr.tenant_id=k.tenant_id AND fr.signing_key_id=k.key_id AND fr.status='UPLOADING'),
(SELECT count(*) FROM firmware_release fr WHERE fr.tenant_id=k.tenant_id AND fr.signing_key_id=k.key_id AND fr.status='READY'),
(SELECT count(*) FROM firmware_rollout ro JOIN firmware_release fr ON fr.id=ro.release_id AND fr.tenant_id=ro.tenant_id WHERE ro.tenant_id=k.tenant_id AND fr.signing_key_id=k.key_id AND ro.status='RUNNING')
FROM firmware_signing_key k JOIN user_account creator ON creator.id=k.created_by AND creator.tenant_id=k.tenant_id
WHERE k.tenant_id=$1::uuid ORDER BY k.created_at DESC,k.key_id`,tenantID)
iferr:=tx.QueryRow(ctx,`SELECT status FROM firmware_signing_key WHERE tenant_id=$1::uuid AND key_id=$2 FOR UPDATE`,tenantID,keyID).Scan(&status);errors.Is(err,pgx.ErrNoRows){
returnErrFirmwareSigningKeyConflict
}elseiferr!=nil{
returnerr
}
ifstatus=="REVOKED"{
returnnil
}
varblockedbool
iferr:=tx.QueryRow(ctx,`SELECT EXISTS(
SELECT 1 FROM firmware_release fr WHERE fr.tenant_id=$1::uuid AND fr.signing_key_id=$2 AND fr.status='UPLOADING'
UNION ALL
SELECT 1 FROM firmware_rollout ro JOIN firmware_release fr ON fr.id=ro.release_id AND fr.tenant_id=ro.tenant_id WHERE ro.tenant_id=$1::uuid AND fr.signing_key_id=$2 AND ro.status='RUNNING'
)`,tenantID,keyID).Scan(&blocked);err!=nil{
returnerr
}
ifblocked{
returnErrFirmwareSigningKeyInUse
}
command,err:=tx.Exec(ctx,`UPDATE firmware_signing_key SET status='REVOKED',revoked_at=now() WHERE tenant_id=$1::uuid AND key_id=$2 AND status='ACTIVE'`,tenantID,keyID)
iferr:=tx.QueryRow(ctx,`SELECT EXISTS(SELECT 1 FROM firmware_signing_key WHERE tenant_id=$1::uuid AND key_id=$2 AND status='ACTIVE')`,a.tenantID,in.SigningKeyID).Scan(&signingKeyActive);err!=nil{
rows,err:=tx.Query(ctx,`SELECT public_id::text,COALESCE(household_id::text,''),model,COALESCE(hardware_revision,''),version,expected_size,expected_digest,signature_algorithm,signature,signing_key_id,COALESCE(minimum_security_version,''),COALESCE(release_notes,''),release_channel,mandatory,published_at,created_source,status,verified_at,created_at,updated_at,object_ref FROM firmware_release WHERE tenant_id=$1::uuid AND household_id=$2::uuid ORDER BY created_at DESC LIMIT 100`,a.tenantID,a.householdID)
count(fa.id) FILTER(WHERE fa.status IN ('DOWNLOADING','INSTALLING') OR (fa.status='ASSIGNED' AND dc.status IN ('DELIVERED','ACKNOWLEDGED','SUCCEEDED','FAILED'))),
iferr:=s.pool.QueryRow(ctx,`SELECT public_key_base64 FROM firmware_signing_key WHERE tenant_id=$1::uuid AND key_id=$2 AND status='ACTIVE'`,a.tenantID,item.SigningKeyID).Scan(&publicKeyBase64);err!=nil{
command,err:=tx.Exec(ctx,`UPDATE firmware_release SET status='READY',verified_at=now(),updated_at=now() WHERE public_id=$1::uuid AND status='UPLOADING'`,publicID)
iferr:=tx.QueryRow(ctx,`SELECT id::text,status FROM firmware_release WHERE tenant_id=$1::uuid AND public_id=$2::uuid FOR UPDATE`,access.tenantID,publicID).Scan(&releaseID,&status);err!=nil{
returnerr
}
ifstatus=="PAUSED"{
returnnil
}
ifstatus!="READY"{
returnErrFirmwareStateConflict
}
command,err:=tx.Exec(ctx,`UPDATE firmware_release SET status='PAUSED',updated_at=now() WHERE id=$1::uuid AND status='READY'`,releaseID)
iferr!=nil{
returnerr
}
ifcommand.RowsAffected()!=1{
returnErrFirmwareStateConflict
}
paused,err:=tx.Exec(ctx,`UPDATE firmware_rollout SET status='PAUSED',updated_at=now() WHERE release_id=$1::uuid AND status='RUNNING'`,releaseID)
iferr!=nil{
returnerr
}
cancelled,err:=tx.Exec(ctx,`UPDATE device_command dc SET status='CANCELLED',completed_at=now(),version=version+1,updated_at=now() FROM firmware_assignment fa JOIN firmware_rollout ro ON ro.id=fa.rollout_id WHERE fa.command_id=dc.id AND ro.release_id=$1::uuid AND ro.status='PAUSED' AND dc.status='QUEUED'`,releaseID)
err:=tx.QueryRow(ctx,`SELECT fr.status,fsk.status FROM firmware_release fr JOIN firmware_signing_key fsk ON fsk.tenant_id=fr.tenant_id AND fsk.key_id=fr.signing_key_id WHERE fr.tenant_id=$1::uuid AND fr.public_id=$2::uuid FOR UPDATE OF fr,fsk`,access.tenantID,publicID).Scan(&status,&keyStatus)
iferrors.Is(err,pgx.ErrNoRows){
returnErrFirmwareSigningKeyInactive
}
iferr!=nil{
returnerr
}
ifstatus=="READY"{
returnnil
}
ifstatus!="PAUSED"{
returnErrFirmwareStateConflict
}
ifkeyStatus!="ACTIVE"{
returnErrFirmwareSigningKeyInactive
}
command,err:=tx.Exec(ctx,`UPDATE firmware_release SET status='READY',updated_at=now() WHERE tenant_id=$1::uuid AND public_id=$2::uuid AND status='PAUSED'`,access.tenantID,publicID)
iferr:=tx.QueryRow(ctx,`SELECT id::text,status,verified_at FROM firmware_release WHERE tenant_id=$1::uuid AND public_id=$2::uuid FOR UPDATE`,access.tenantID,publicID).Scan(&releaseID,&status,&verifiedAt);err!=nil{
iferr:=tx.QueryRow(ctx,`SELECT EXISTS(SELECT 1 FROM firmware_rollout WHERE release_id=$1::uuid AND status='RUNNING')`,releaseID).Scan(&running);err!=nil{
returnerr
}
ifrunning{
returnErrFirmwareReleaseInUse
}
removeObject=false
}
command,err:=tx.Exec(ctx,`UPDATE firmware_release SET status='RETIRED',updated_at=now() WHERE id=$1::uuid AND status=$2`,releaseID,status)
err:=s.pool.QueryRow(ctx,`SELECT fr.public_id::text,COALESCE(fr.household_id::text,''),fr.model,COALESCE(fr.hardware_revision,''),fr.version,fr.expected_size,fr.expected_digest,fr.signature_algorithm,fr.signature,fr.signing_key_id,COALESCE(fr.minimum_security_version,''),COALESCE(fr.release_notes,''),fr.release_channel,fr.mandatory,fr.published_at,fr.created_source,fr.status,fr.verified_at,fr.created_at,fr.updated_at,fr.object_ref,fr.tenant_id::text,ua.id::text,ua.public_id::text,hm.role,h.id::text,h.public_id::text FROM firmware_release fr JOIN household h ON h.id=fr.household_id AND h.tenant_id=fr.tenant_id JOIN household_member hm ON hm.household_id=h.id AND hm.status='active' JOIN user_account ua ON ua.id=hm.user_id AND ua.tenant_id=fr.tenant_id AND ua.status='active' WHERE fr.public_id=$1::uuid AND ua.oidc_issuer=$2 AND ua.oidc_subject=$3 LIMIT 1`,publicID,p.Issuer,p.Subject).Scan(append(firmwareReleaseTargets(&item),&a.tenantID,&a.userID,&a.userPublicID,&role,&a.householdID,&a.householdPublicID)...)
err=tx.QueryRow(ctx,`SELECT fr.id::text,fr.model,COALESCE(fr.hardware_revision,''),fr.version,fr.expected_digest,fr.signature,fr.signing_key_id FROM firmware_release fr JOIN firmware_signing_key fsk ON fsk.tenant_id=fr.tenant_id AND fsk.key_id=fr.signing_key_id AND fsk.status='ACTIVE' WHERE fr.tenant_id=$1::uuid AND fr.household_id=$2::uuid AND fr.public_id=$3::uuid AND fr.status='READY' FOR SHARE OF fr,fsk`,a.tenantID,a.householdID,releasePublicID).Scan(&releaseID,&model,&hardware,&version,&digest,&signature,&keyID)
iferrors.Is(err,pgx.ErrNoRows){
returnErrFirmwareStateConflict
}
iferr!=nil{
returnerr
}
varrolloutIDstring
err=tx.QueryRow(ctx,`INSERT INTO firmware_rollout(tenant_id,household_id,release_id,name,status,target_percentage,created_by,started_at) VALUES($1::uuid,$2::uuid,$3::uuid,$4,'RUNNING',$5,$6::uuid,now()) RETURNING id::text,public_id::text,created_at,updated_at`,a.tenantID,a.householdID,releaseID,name,percentage,a.userID).Scan(&rolloutID,&result.ID,&result.CreatedAt,&result.UpdatedAt)
iferr!=nil{
returnerr
}
result.ReleaseID=releasePublicID
result.HouseholdID=householdPublicID
result.Name=name
result.Status="RUNNING"
result.TargetPercentage=percentage
selected:=0
for_,devicePublicID:=rangedeviceIDs{
h:=sha256.Sum256([]byte(devicePublicID))
ifint(h[0])%100>=percentage&&selected>0{
continue
}
vardeviceID,previousstring
err:=tx.QueryRow(ctx,`SELECT d.id::text,COALESCE(dt.firmware_version,'') FROM device d JOIN device_twin dt ON dt.device_id=d.id JOIN device_binding b ON b.device_id=d.id AND b.household_id=$2::uuid AND b.unbound_at IS NULL WHERE d.tenant_id=$1::uuid AND d.public_id=$3::uuid AND d.model=$4 AND ($5='' OR d.hardware_revision=$5)`,a.tenantID,a.householdID,devicePublicID,model,hardware).Scan(&deviceID,&previous)
iferr!=nil{
returnfmt.Errorf("rollout target %s is incompatible or inaccessible",devicePublicID)
err=tx.QueryRow(ctx,`INSERT INTO device_command(tenant_id,device_id,command_type,payload,requested_by,idempotency_key,request_digest,expires_at) VALUES($1::uuid,$2::uuid,'firmware_update',$3::jsonb,$4::uuid,$5,$6,now()+interval '24 hours') RETURNING id::text`,a.tenantID,deviceID,payload,a.userID,dedupe,hex.EncodeToString(requestDigest[:])).Scan(&commandID)
iferr!=nil{
returnerr
}
if_,err:=tx.Exec(ctx,`INSERT INTO firmware_assignment(rollout_id,tenant_id,device_id,command_id,previous_version,status) VALUES($1::uuid,$2::uuid,$3::uuid,$4::uuid,NULLIF($5,''),'ASSIGNED')`,rolloutID,a.tenantID,deviceID,commandID,previous);err!=nil{
err:=s.pool.QueryRow(ctx,`SELECT ro.public_id::text,fr.public_id::text,h.public_id::text,ro.name,ro.status,ro.target_percentage,count(fa.id),count(fa.id) FILTER(WHERE fa.status='CONFIRMED'),count(fa.id) FILTER(WHERE fa.status='FAILED'),ro.created_at,ro.updated_at,hm.role FROM firmware_rollout ro JOIN firmware_release fr ON fr.id=ro.release_id JOIN household h ON h.id=ro.household_id LEFT JOIN firmware_assignment fa ON fa.rollout_id=ro.id JOIN household_member hm ON hm.household_id=h.id AND hm.status='active' JOIN user_account ua ON ua.id=hm.user_id AND ua.tenant_id=ro.tenant_id AND ua.status='active' WHERE ro.public_id=$1::uuid AND ua.oidc_issuer=$2 AND ua.oidc_subject=$3 GROUP BY ro.id,fr.public_id,h.public_id,hm.role`,publicID,p.Issuer,p.Subject).Scan(&item.ID,&item.ReleaseID,&item.HouseholdID,&item.Name,&item.Status,&item.TargetPercentage,&targeted,&succeeded,&failed,&item.CreatedAt,&item.UpdatedAt,&role)
rows,err:=tx.Query(ctx,`SELECT ro.public_id::text,fr.public_id::text,h.public_id::text,ro.name,ro.status,ro.target_percentage,count(fa.id),count(fa.id) FILTER(WHERE fa.status='CONFIRMED'),count(fa.id) FILTER(WHERE fa.status='FAILED'),ro.created_at,ro.updated_at FROM firmware_rollout ro JOIN firmware_release fr ON fr.id=ro.release_id JOIN household h ON h.id=ro.household_id LEFT JOIN firmware_assignment fa ON fa.rollout_id=ro.id WHERE ro.tenant_id=$1::uuid AND ro.household_id=$2::uuid GROUP BY ro.id,fr.public_id,h.public_id ORDER BY ro.created_at DESC LIMIT 100`,a.tenantID,a.householdID)
rows,err:=s.pool.Query(ctx,`SELECT d.public_id::text,d.model,COALESCE(fa.previous_version,''),fa.status,fa.progress_percent,fa.last_result,fa.last_reported_at,fa.updated_at FROM firmware_assignment fa JOIN firmware_rollout ro ON ro.id=fa.rollout_id JOIN device d ON d.id=fa.device_id WHERE ro.public_id=$1::uuid ORDER BY d.public_id`,rolloutPublicID)
err:=tx.QueryRow(ctx,`SELECT ro.tenant_id::text,ua.public_id::text FROM firmware_rollout ro JOIN household_member hm ON hm.household_id=ro.household_id AND hm.status='active' JOIN user_account ua ON ua.id=hm.user_id AND ua.tenant_id=ro.tenant_id WHERE ro.public_id=$1::uuid AND ua.oidc_issuer=$2 AND ua.oidc_subject=$3 AND hm.role IN ('owner','admin') FOR UPDATE OF ro`,publicID,p.Issuer,p.Subject).Scan(&tenantID,&userPublicID)
iferr!=nil{
returnErrAccessDenied
}
if_,err:=tx.Exec(ctx,`UPDATE firmware_rollout SET status='PAUSED',updated_at=now() WHERE public_id=$1::uuid AND status='RUNNING'`,publicID);err!=nil{
returnerr
}
if_,err:=tx.Exec(ctx,`UPDATE device_command dc SET status='CANCELLED',completed_at=now(),version=version+1,updated_at=now() FROM firmware_assignment fa JOIN firmware_rollout ro ON ro.id=fa.rollout_id WHERE fa.command_id=dc.id AND ro.public_id=$1::uuid AND dc.status='QUEUED'`,publicID);err!=nil{
rows,err:=s.pool.Query(ctx,`SELECT d.public_id::text FROM firmware_assignment fa JOIN firmware_rollout ro ON ro.id=fa.rollout_id JOIN device d ON d.id=fa.device_id WHERE ro.public_id=$1::uuid ORDER BY d.public_id`,rolloutPublicID)
err:=s.pool.QueryRow(ctx,`SELECT fr.object_ref,fr.version FROM firmware_release fr JOIN firmware_rollout ro ON ro.release_id=fr.id AND ro.status IN ('RUNNING','COMPLETED') JOIN firmware_assignment fa ON fa.rollout_id=ro.id AND fa.device_id=$2::uuid WHERE fr.public_id=$1::uuid AND fr.tenant_id=$3::uuid AND fr.status='READY' AND fa.status IN ('ASSIGNED','DOWNLOADING','INSTALLING','CONFIRMED')`,releasePublicID,id.ID,id.TenantID).Scan(&objectRef,&version)