package onboarding import ( "data-terminal-cloud/internal/deviceauth" "encoding/json" "net/http" "regexp" "strings" ) var runtimePath = regexp.MustCompile(`^/device/v(?:2/conversations|3/agent-sessions)/([0-9a-f-]{36})(?:/(events|heartbeat|stop|activate|turns:batch|upload-batches))?$`) func (s *Service) runtimeAdmission(r *http.Request, d Device, raw []byte) (bool, error) { create := r.URL.Path == "/device/v3/agent-sessions" match := runtimePath.FindStringSubmatch(r.URL.Path) if r.URL.Path == "/device/v2/conversations" { return false, deviceauth.ErrDeviceInactive } if len(match) > 0 { var current bool err := s.pool.QueryRow(r.Context(), `SELECT EXISTS(SELECT 1 FROM conversation WHERE public_id=$1::uuid AND device_id=$2::uuid AND onboarding_generation=$3)`, match[1], d.ID, d.Generation).Scan(¤t) if err != nil { return false, err } if !current { return false, deviceauth.ErrDeviceInactive } } if !create && len(match) == 0 { parts := strings.Split(r.URL.Path, "/") if len(parts) >= 5 && (parts[3] == "upload-batches" || parts[3] == "media-segments") { if !uuidValid(parts[4]) { return false, deviceauth.ErrCredentialInvalid } table := "upload_batch" if parts[3] == "media-segments" { table = "media_segment" } var current bool err := s.pool.QueryRow(r.Context(), `SELECT EXISTS(SELECT 1 FROM `+table+` m JOIN conversation c ON c.id=m.conversation_id WHERE m.public_id=$1::uuid AND c.device_id=$2::uuid AND c.onboarding_generation=$3)`, parts[4], d.ID, d.Generation).Scan(¤t) if err != nil { return false, err } if !current { return false, deviceauth.ErrDeviceInactive } } return false, nil } var intent, activation, attempt, token string if create { var input struct { Intent string `json:"intent"` Activation string `json:"activation_id"` Attempt string `json:"attempt_id"` Token string `json:"permit_token"` } if err := json.Unmarshal(raw, &input); err != nil { return false, deviceauth.ErrCredentialInvalid } intent = input.Intent activation = input.Activation attempt = input.Attempt token = input.Token } var ready bool err := s.pool.QueryRow(r.Context(), `SELECT EXISTS(SELECT 1 FROM device_activation_job j JOIN device_binding b ON b.device_id=j.device_id AND b.generation=j.binding_generation AND b.unbound_at IS NULL WHERE j.device_id=$1::uuid AND j.binding_generation=$2 AND j.status='READY' AND j.config_ack_at IS NOT NULL AND j.config_expires_at>now())`, d.ID, d.Generation).Scan(&ready) if err != nil { return false, err } if ready && intent != "activation_test" { return false, nil } var valid bool if create { if intent != "activation_test" || !uuidV4(activation) || !uuidV4(attempt) || (token != "" && !validB64(token, 32)) { return false, deviceauth.ErrDeviceInactive } err = s.pool.QueryRow(r.Context(), `SELECT EXISTS(SELECT 1 FROM device_activation_job j JOIN device_activation_attempt a ON a.activation_id=j.id JOIN device_binding b ON b.device_id=j.device_id AND b.generation=j.binding_generation AND b.unbound_at IS NULL WHERE j.device_id=$1::uuid AND j.id=$2::uuid AND a.id=$3::uuid AND j.binding_generation=$4 AND a.binding_generation=$4 AND a.config_version=j.config_version AND j.status IN ('REGISTERED_OBSERVED','CONTACT_POSSIBLE','READY') AND j.config_ack_at IS NOT NULL AND j.engine_ready_at IS NOT NULL AND j.config_expires_at>now() AND a.stage='CONVERSATION_TEST' AND a.executor='DEVICE' AND a.status='CONTACT_POSSIBLE' AND (a.permit_hash IS NULL OR a.permit_hash=$5) AND (a.permit_expires_at>now() OR a.conversation_id IS NOT NULL))`, d.ID, activation, attempt, d.Generation, digest([]byte(token))).Scan(&valid) } else { if len(match) > 2 && !oneOf(match[2], "", "events", "heartbeat", "stop") { return false, deviceauth.ErrDeviceInactive } err = s.pool.QueryRow(r.Context(), `SELECT EXISTS(SELECT 1 FROM conversation c JOIN device_activation_attempt a ON a.conversation_id=c.id JOIN device_activation_job j ON j.id=a.activation_id WHERE c.public_id=$1::uuid AND c.device_id=$2::uuid AND j.binding_generation=$3 AND a.binding_generation=$3 AND a.config_version=j.config_version AND a.stage='CONVERSATION_TEST' AND a.status IN ('CONTACT_POSSIBLE','SUCCESS_OBSERVED','UNKNOWN'))`, match[1], d.ID, d.Generation).Scan(&valid) } if err != nil { return false, err } if !valid { return false, deviceauth.ErrDeviceInactive } return true, nil }